0
votes

I am new to iOS programming and am trying to manipulate some audio characteristics of an audio file which requires the audio data as float values which am able to successfully obtain.

I am stuck on how to play back that float values as audio data. I investigated a lot of iOS frameworks using its documentation but most of them do not allow me to work on float data. Its mostly reading and playing back audio files & controlling some playback parameters.

In short:

Objective: Playback a buffer/array of float values (originally audio data) as audio.

Overall Process:Audio File -> Read to float buffer (done) -> manipulate (can do) -> playback as audio (do not want to store as file)

Apologies if the question is very naive. All help is appreciated. Thanks.

3
You can use AVAudioPlayer with in-memory buffers. developer.apple.com/library/prerelease/ios/documentation/… - sbooth

3 Answers

0
votes

I second sbooth's comments. For a good tutorial on playback, look for the 2014 WWDC Videos. You want to watch:

0
votes

If you use the AVAudioPlayer, there is an initWithData that takes NSData as a parameter. So it looks like your challenge is to loading your float buffer into NSData.

You have not commented on the format of your float buffer (i.e. pcm, mono, stereo, interleaved, etc. )
If you need low latency, more granular features, or a more obscure audio format, you can also use a RemoteIO audio unit to play back buffers of audio. You should be able to feed it a buffer of floats assuming that you initialize the AudioStreamBasicDescription correctly so that it is compatible with your audio format.

0
votes

Thanks @jaybers I followed a similar approach for the solution. Apologies for not posting it earlier.

Solution: 1) I built/coded the header for playback (PCM as its easiest) in a BYTE * type array. 2) Appended the header to a NSDATA array. 3) appended the float data to NSDATA array 4) played it using AVAudioPlayer ....

An issue I faced : My data was 16bits while float is 32 bit in IOS so playing it as 16bit PCM / 32 bit PCM was introducing noise - I think because of the extra zeros. So i transferred the float data into short datatype array and appended that to the NSDATA and played it as 16bit-PCM - perfectly played.

Codes:

//mynewdata1 is a short datatype 16bit array

NSData *Wave1= [NSMutableData dataWithData:mynewdata1]; 

unsigned long totalAudioLen=[Wave1 length];
unsigned long totalDataLen = totalAudioLen + 44;
unsigned long longSampleRate = 4*11025.0;
unsigned int channels = 1;
unsigned long byteRate = (16 * longSampleRate * channels)/8;

Byte *header = (Byte*)malloc(44);
header[0] = 'R';  // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (Byte) (totalDataLen & 0xff);
header[5] = (Byte) ((totalDataLen >> 8) & 0xff);
header[6] = (Byte) ((totalDataLen >> 16) & 0xff);
header[7] = (Byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f';  // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16;  // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1;  // format = 1 for pcm and 2 for byte integer
header[21] = 0;
header[22] = (Byte) channels;
header[23] = 0;
header[24] = (Byte) (longSampleRate & 0xff);
header[25] = (Byte) ((longSampleRate >> 8) & 0xff);
header[26] = (Byte) ((longSampleRate >> 16) & 0xff);
header[27] = (Byte) ((longSampleRate >> 24) & 0xff);
header[28] = (Byte) (byteRate & 0xff);
header[29] = (Byte) ((byteRate >> 8) & 0xff);
header[30] = (Byte) ((byteRate >> 16) & 0xff);
header[31] = (Byte) ((byteRate >> 24) & 0xff);
header[32] = (Byte) (16*1)/8;  // block align
header[33] = 0;
header[34] = 16;  // bits per sample
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (Byte) (totalAudioLen & 0xff);
header[41] = (Byte) ((totalAudioLen >> 8) & 0xff);
header[42] = (Byte) ((totalAudioLen >> 16) & 0xff);
header[43] = (Byte) ((totalAudioLen >> 24) & 0xff);

NSData *headerData = [NSData dataWithBytes:header length:44];
NSMutableData * soundFileData1 = [NSMutableData alloc];
[soundFileData1 appendData:headerData];
[soundFileData1 appendData:Wave1];

self.avap1 = [[AVAudioPlayer alloc] initWithData:soundFileData1 fileTypeHint:@"wav" error:&error1];
[self.avap3 play]; //to play