Search code examples
iosobjective-ccore-audio

iOS float buffer to audio playback


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.


Solution

  • 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