Real time audio processing Swift - ios

Our app continuously records and processes audio from iPhone mic.
Currently I use AVAudioRecorder and AVFoundation and record audio inout into 8 sec ".wav" files.
Instead I want continuously to record audio input into buffer and process 8 sec length buffer's chunks.
How can I record audio input into buffer and how can I read 8 sec length chunks from there?
Thanks!

You could receive the raw PCM a number of ways (in AV Foundation: AVCaptureAudioDataOutput from an AVCaptureDevice, or AVAudioEngine with a processing tap inserted; in Audio Toolbox: Audio Queue Services, the RemoteIO audio unit), then to write the file, you could use Audio Toolbox's AudioFile or ExtAudioFile, just counting up how many frames you've written and deciding when it's time to start a new 8 sec file.
As Rhythmic Fistman notes above, it would be safer if you did something like
capture callbacks --pushes-to--> ring buffer <--pulls-from-- file-writing code
Because when you're closing one file and opening another, the capture callbacks are still going to be coming in, and if you block on file I/O you stand a very good chance of dropping some data on the floor.
I suppose another approach would be to just fill an 8 sec buffer in memory from your callbacks, and when it's full, have another thread write that file while you malloc a new buffer and start recording into that (obviously, the file writer would dispose the old buffer when it's done).
Edit: Also, I didn't see anything about Swift in your question, but any of this should work fine from Swift or C/Obj-C.

Related

record pcmaudiodata per 10 milisecond without playback

İ need to record pcmaudio per 10 milisecond without playback in swift.
I have tried this code but i can't find how can i stop playback while recording.
RecordAudio Github Repo
and second question: How can i get PCM data from circular buffer for encode-decode process properly. When I convert recorded audio data to signed byte or unsigned byte or anything else the converted data sometimes will corrupt. What is the best practice for this kind of process
In the RecordAudio sample code, the audio format is specified as Float (32-bit floats). When doing a float to integer conversion, you have to make sure your scale and offset results in a value in legal range for the destination type. e.g. check that -1.0 to 1.0 results in 0 to 256 (unsigned byte), and out-of-range values are clipped to legal values. Also pay attention to the number of samples you convert, as an Audio Unit callback can vary the frameCount sent (number of samples returned). You most likely won't get exactly 10 mS in any single RemoteIO callback, but may have to observe a circular buffer filled by multiple callbacks, or a larger buffer that you will have to split.
When RemoteIO is running in play-and-record mode, you can usually silence playback by zeroing the bufferList buffers (after copying, analyzing, or otherwise using the data in the buffers) before returning from the Audio Unit callback.

Record and send audio data to c++ function

I need to send audio data in real-time in PCM format 8 KHz 16 Bit Mono.
Audio must been sent like array of chars with length
(<#char *data#>, <#int len#>).
Now I'm beginner in Audio processing and cant really understand how to accomplish that. My best try was been to convert to iLBC format and try but it couldn't work. Is there any sample how to record and convert audio to any format. I have already read Learning Core Audio from Chris Adamson and Kevin Avila but I really didn't find solution that works.
Simple what i need:
(record)->(convert?)-> send(char *data, int length);
Couse I need to send data like arrays of chars i cant use player.
EDIT:
I managed to make everything work with recording and with reading buffers. What I can't manage is :
if (ref[i]->mAudioDataByteSize != 0){
char * data = (char*)ref[i]->mAudioData;
sendData(mHandle, data, ref[i]->mAudioDataByteSize);
}
This is not really a beginner task. The solutions are to use either the RemoteIO Audio Unit, the Audio Queue API, or an AVAudioEngine installTapOnBus block. These will give you near real-time (depending on the buffer size) buffers of audio samples (Int16's or Floats, etc.) that you can convert, compress, pack into other data types or arrays, etc. Usually by calling a callback function or block that you provide to do whatever you want with the incoming recorded audio sample buffers.

Where should I perform File IO workload in PortAudio if not in the callbacks

I am using PortAudio to record multichannel audio data. I want to save the data from each channel as a separate file. Therefore, I have to do some File IO work somewhere in the program. Since the document recommend not doing any IO work in the callback function since they are called in a high frequency.
Then, what is the right way to perform the IO work ? Should I start another thread?
Thanks in advance for your time on reading my post!
This is what I would do:
1) Have a buffer for each channel. These buffers will be your storage buffers and not the ones you have in the callback. I'd suggest declarinng these buffers in your paData structures. You'll have to decide the buffer length according to how much storage you have or time limit.
2) When you stop the recording, have it call a method which does your file IO work.
3) Use the buffers you had from step 1 and write to the file.
4) Repeat

What's the reason of using Circular Buffer in iOS Audio Calling APP?

My question is pretty much self explanatory. Sorry if it seems too dumb.
I am writing a iOS VoIP dialer and have checked some open-source code(iOS audio calling app). And almost all of those use Circular Buffer for storing recorded and received PCM audio data. SO i am wondering why we need to use a Circular Buffer in this case. What's the exact reason for using such audio buffer.
Thanks in advance.
Using a circular buffer lets you process the input and output data asynchronously from it's source. The audio render process takes place on a high priority thread. It asks for audio samples from your app (playback), and offers audio (recording/processing) on a timer in the form of callbacks.
A typical scenario would be for the audio callback to fire every 0.023 seconds to ask for (and/or offer) 1024 samples of audio. This thread is synchronized with system hardware so it is imperative that your callback returns before the 0.023 seconds is up. If you don't, the hardware won't wait for you, it will just skip that cycle and you will have an audible pop or silence, or miss audio you are trying to record.
A circular buffer's place is to pass data between threads. In an audio application that would be moving the samples to and from the audio thread asynchronously. One thread produces samples on to the "head" of the buffer, and the other thread consumes them from the "tail".
Here's an example, retrieving audio samples from the microphone and writing them to disk. Your app has subscribed to a callback that fires every 0.023 seconds, offering 1024 samples to be recorded. The naive approach would be to simply write the audio to disk from within that callback.
void myCallback(float *samples,int sampleCount, SampleSaver *saver){
SampleSaverSaveSamples(saver,samples,sampleCount);
}
This will work!! Most of the time...
The problem is that there is no guarantee that writing to disk will finish before 0.023 seconds, so every now and then, your recording has a pop in it because SampleSaver just plain took too long and the hardware just skips the next callback.
The right way to do this is to use a circular buffer. I personally use TPCircularBuffer because it's awesome. The way it works (externally) is that you ask the buffer for a pointer to write data to (the head) on one thread, then on another thread you ask the buffer for a pointer to read from (the tail). Here's how it would be done using TPCircularBuffer (skipping setup and using a simplified callback).
//this is on the high priority thread that can't wait for anything like a slow write to disk
void myCallback(float *samples,int sampleCount, TPCircularBuffer *buffer){
int32_t availableBytes = 0;
float *head = TPCircularBufferHead(buffer, &availableBytes);
memcpy(head,samples,sampleCount * sizeof(float));//copies samples to head
TPCircularBufferProduce(buffer,sampleCount * sizeof(float)); //moves buffer head "forward in the circle"
}
This operation is super quick and puts no extra pressure on that sensitive audio thread. You then create your own timer a separate thread to write the samples to disk.
//this is on some background thread that can take it's sweet time
void myLeisurelySavingCallback(TPCircularBuffer *buffer, SampleSaver *saver){
int32_t available;
float *tail = TPCircularBufferTail(buffer, &available);
int samplesInBuffer = available / sizeof(float); //mono
SampleSaverSaveSamples(saver, tail, samplesInBuffer);
TPCircularBufferConsume(buffer, samplesInBuffer * sizeof(float)); // moves tail forward
}
And there you have it, not only do you avoid audio glitches, but if you initialize a big enough buffer, you can set your write to disk callback to only fire every second or two (after the circular buffer has built up a good bit of audio) which is much easier on your system than writing to disk every 0.023 seconds!
The main reason to use the buffer is so the samples can be handled asynchronously. They are a great way to pass messages between threads without locks as well. Here is a good article explaining a neat memory trick for the implementation of a circular buffer.
Good question. There is another good reason for using Circular Buffer.
In iOS, if you use callbacks(Audio unit) for recording and playing audio(In-fact you need to use it if you want to create a real-time audio transferring app) then you will get a chunk of data for a specific amount of time(let's say 20 milliseconds) from the recorder callback. And in iOS, you will never get fixed length of data always(If you set the callback interval as 20ms then you will get 370 or 372 bytes of data. And you will never know when you will get 370 bytes or 372 bytes. Correct me if i am wrong). Then, to transfer the audio through UDP packets you need to use a codec for data encoding and decoding(G729 is generally used for VoIP apps). But g729 takes data by the multiplier of 8. Assume, you encode 368(8*46) bytes per 20ms. So what are you going to do with rest of the data ? You need to store it by sequence for the next chunk to process.
SO that's the reason. There are some other details thing but i kapt it simple for your better understanding. Just comment below if you have any question.

how to get 3sn of audio buffer ios

how can I get 3sn of samples of an audio that is being recorded. I have used RemoteIO audiounit and it brings 512 samples and it is 10 milisecond. I need total 3sec of samples? Can you give me an idea how to do it .
here is my another post with details of my code Concatenating Audio Buffers in ObjectiveC
my worst sceneario will be recording the audio in a file then get its samples. I dont want to go with this.
should I use AudioQueue ? Any Advice?
I really need help. thanks
Save the buffers (giving to you by the Audio Unit callback) to an array (C array), and increment the index of the array used for saving data by 512 after every 512 samples of input data.
I have append the frames that came with each render like hotpaw2 said. now you can find the detailed codes, how I applied buffers in my this post/question
Concatenating Audio Buffers in ObjectiveC
thanks

Resources