Real time access to microphone audio

I would like to get real time access to audio from a device (android/iOS/windows) using C++ Builder but am not having much luck so far.  Basically I want to pass the microphone audio straight to the speakers.  The TAudioCaptureDevice component is great and all but can only save audio to a file for later playback.  Is there a way to modify that component to output a stream rather than save to a file?  I tried accessing the file TAudioCaptureDevice creates as it records but I'm assuming wav files require a header/footer that is only written when recording is finished.

I have also tried digging into native code (i.e. AVFoundation for iOS) but don't have much experience with manipulating those modules in C++.  Got as far as creating a capture session and connecting the audio input but not sure where to go from there.

Any pointers would be appreciated, thanks.

  • I got it working in Android using native API (TJAudioRecord, can post the code if anyone is interested) but am still struggling with iOS.

    Using AVFoundation I've got as far as creating an AVCaptureSession, AVCaptureDevice and AVCaptureDeviceInput and linking them but I can't seem to create the AVCaptureAudioDataOutput to actually read the buffer data.  I've been working off examples created in Delphi and trying to translate to C++.  Here's what I've got so far:

      AVCaptureSession         *captureSession;
      AVCaptureDevice          *captureAudioDevice;
      AVCaptureDeviceInput     *captureDeviceAudioInput;
      AVCaptureAudioDataOutput *captureAudioDataOutput;
      PPointer                  error;
      Macapi::Dispatch::dispatch_queue_t  AudioQueue;
      TAudioSampleDelegate      audioSampleDelegate;
      captureSession          = TAVCaptureSession::Create();
      audioSampleDelegate     = TAudioSampleDelegate::Create();
      captureAudioDevice      = TAVCaptureDevice::Wrap(TAVCaptureDevice::OCClass->defaultDeviceWithMediaType(AVMediaTypeAudio()));
      captureDeviceAudioInput = TAVCaptureDeviceInput::Wrap(TAVCaptureDeviceInput::OCClass->deviceInputWithDevice(captureAudioDevice, error));
      captureAudioDataOutput  = TAVCaptureAudioDataOutput::Create();
      AudioQueue = (Macapi::Dispatch::dispatch_queue_t)(int)dispatch_queue_create("Audio Capture Queue", 0);
      //captureAudioDataOutput->setSampleBufferDelegate(ILocalObject(audioSampleDelegate).GetObjectID, AudioQueue);

    This all compiles fine (after some fiddling) except for the sample buffer delegate object.  The Delphi code I was working of declares it like so:

      TAudioSampleDelegate = class( TOCLocal, AVCaptureVideoDataOutputSampleBufferDelegate )
        procedure captureOutput( captureOutput: AVCaptureOutput; didOutputSampleBuffer: CMSampleBufferRef; fromConnection: AVCaptureConnection ); cdecl;

    Which I translated to:

    class TAudioSampleDelegate: public TOCLocal, public AVCaptureVideoDataOutputSampleBufferDelegate
      void __cdecl captureOutput(_di_AVCaptureOutput captureOutput, void * didOutputSampleBuffer, _di_AVCaptureConnection fromConnection);

    The error I get from this is that there is no member named 'Create' in TAudioSampleDelegate so I can't initialize the object.  I would have assumed this was handled in the parent classes somewhere but it keeps telling me that the class I created is abstract, i.e. if I try 'new TAudioSampleDelegate' instead of 'TAudioSampleDelegate::Create()' I get the compile error 'allocating an object of abstract class type 'TAudioSampleDelegate''.

    Hopefully someone has experience with these functions and can tell me what I'm doing wrong.