1

I have written an audio WAV (have recorded my voice) file using AVAudioRecorder. The final file format is a WAV file. File was successfully saved and I can hear my voice. I want to send this file to a back End server (web-service). But my server accepting only data and FMT information in WAV . It is not accepting my wav file because of my wav file infromation with FLLR, data, FMT. I have checked my WAV file information in Riffpad tool. It's showing FLLR, data, FMT. But I want only data and fmt. Because my server side accepts only data and FMT. So please advice how to remove FLLR in my wav file in programmatically?

enter image description here

My source code for the record:

  NSError *error;

    // Recording settings
    NSMutableDictionary *settings = [NSMutableDictionary dictionary];
    [settings setValue: [NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
    [settings setValue: [NSNumber numberWithFloat:22050] forKey:AVSampleRateKey];
    [settings setValue: [NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey]; // mono
    [settings setValue: [NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
    [settings setValue: [NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
    //[settings setValue: [NSNumber numberWithInt:16] forKey:AudioSampleType];




    // File URL
    NSURL *url = [NSURL fileURLWithPath:FILEPATH];

    //NSLog(@"Url file path ::: %@",url);

    // Create recorder
    recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
    if (!recorder)
    {
//        NSLog(@"Error establishing recorder: %@", error.localizedFailureReason);
        return;
    }
2vision2
  • 4,933
  • 16
  • 83
  • 164
  • Can you WS skip the FLLR, as suggested here: http://stackoverflow.com/questions/6284651/avaudiorecorder-doesnt-write-out-proper-wav-file-header – Larme Sep 01 '15 at 12:45
  • thanks for your message. Can you please explain WS means ? – 2vision2 Sep 01 '15 at 14:14
  • WebService. As suggested in the linked answer, it would be better and simpler of your server just skip the FLLR – Larme Sep 01 '15 at 14:29
  • there is no way in front(objective c) end? – 2vision2 Sep 01 '15 at 15:27
  • According to the linked answer, it's some chunk data added by Apple implementation. So unless you know exactly what it does (maybe some research on the web can tell you what exactly), this could be quite difficult. There is maybe another element (in GitHub) than AVAudioRecorder that do it. – Larme Sep 02 '15 at 12:09

2 Answers2

2

Thank God and your support friends. Yes finally i solved my issues. I don't know the way is correct. But my issues is solved. I recorded voice using above code and save my audio .Then again i will export the audio using the following code. I got this code from https://developer.ibm.com/answers/questions/180732/seems-watson-text-to-speech-service-returns-a-wav.html

-(NSData*) stripAndAddWavHeader:(NSData*) wav {
    unsigned long wavDataSize = [wav length] - 44;

    NSData *WaveFile= [NSMutableData dataWithData:[wav subdataWithRange:NSMakeRange(44, wavDataSize)]];

    NSMutableData *newWavData;
    newWavData = [self addWavHeader:WaveFile];

    return newWavData;
   }


 - (NSMutableData *)addWavHeader:(NSData *)wavNoheader {

       int headerSize = 44;
       long totalAudioLen = [wavNoheader length];
       long totalDataLen = [wavNoheader length] + headerSize-8;
       long longSampleRate = 22050.0;
       int channels = 1;
       long byteRate = 8 * 44100.0 * 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
     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) (2 * 8 / 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);

     NSMutableData *newWavData = [NSMutableData dataWithBytes:header length:44];
     [newWavData appendBytes:[wavNoheader bytes] length:[wavNoheader length]];
     return newWavData;
 }
2vision2
  • 4,933
  • 16
  • 83
  • 164
2

Solution on Swift with seeking edges of data


class MediaUtil {
    
    private static func dataToUTF8String(data: NSData, offset: Int, length: Int) -> String? {
        let range = NSMakeRange(offset, length)
        let subdata = data.subdata(with: range)
        return String(data: subdata, encoding: String.Encoding.utf8)
    }
    
    private static func dataToUInt32(data: NSData, offset: Int) -> Int {
        var num: UInt32 = 0
        let length = 4
        let range = NSMakeRange(offset, length)
        data.getBytes(&num, range: range)
        return Int(num)
    }
    
    static func repairWAVHeader(data: NSMutableData)->Data {
        
        // resources for WAV header format:
        // [1] http://unusedino.de/ec64/technical/formats/wav.html
        // [2] http://soundfile.sapp.org/doc/WaveFormat/
        
        var newData = Data()
        
        // update RIFF chunk size
        let fileLength = data.length
        var riffChunkSize = UInt32(fileLength - 8)
        let riffChunkSizeRange = NSMakeRange(4, 4)
        data.replaceBytes(in: riffChunkSizeRange, withBytes: &riffChunkSize)
        
        // find data subchunk
        var subchunkID: String?
        var subchunkSize = 0
        var fieldOffset = 12
        let fieldSize = 4
        while true {
            // prevent running off the end of the byte buffer
            if fieldOffset + 2*fieldSize >= data.length {
                return newData
            }
            
            // read subchunk ID
            subchunkID = dataToUTF8String(data: data, offset: fieldOffset, length: fieldSize)
            fieldOffset += fieldSize
            if subchunkID == "data" {
                break
            }
            
            // read subchunk size
            subchunkSize = dataToUInt32(data: data, offset: fieldOffset)
            fieldOffset += fieldSize + subchunkSize
        }
        
        let rllrRange = NSMakeRange(0, fieldOffset)

        data.replaceBytes(in: rllrRange, withBytes: nil, length: 0)
        newData = newWavHeader(pcmDataLength: data.length)
        newData.append(data as Data)
        return newData
    }
    
    private static func newWavHeader(pcmDataLength: Int) -> Data {
        var header = Data()
        let headerSize = 44
        let bitsPerSample = Int32(16)
        let numChannels: Int32 = 1
        let sampleRate: Int32 = 16000
        
        // RIFF chunk descriptor
        let chunkID = [UInt8]("RIFF".utf8)
        header.append(chunkID, count: 4)
        
        var chunkSize = Int32(pcmDataLength + headerSize - 4).littleEndian
        let chunkSizePointer = UnsafeBufferPointer(start: &chunkSize, count: 1)
        header.append(chunkSizePointer)
        
        let format = [UInt8]("WAVE".utf8)
        header.append(format, count: 4)
        
        // "fmt" sub-chunk
        let subchunk1ID = [UInt8]("fmt ".utf8)
        header.append(subchunk1ID, count: 4)
        
        var subchunk1Size = Int32(16).littleEndian
        let subchunk1SizePointer = UnsafeBufferPointer(start: &subchunk1Size, count: 1)
        header.append(subchunk1SizePointer)
        
        var audioFormat = Int16(1).littleEndian
        let audioFormatPointer = UnsafeBufferPointer(start: &audioFormat, count: 1)
        header.append(audioFormatPointer)
        
        var headerNumChannels = Int16(numChannels).littleEndian
        let headerNumChannelsPointer = UnsafeBufferPointer(start: &headerNumChannels, count: 1)
        header.append(headerNumChannelsPointer)
        
        var headerSampleRate = Int32(sampleRate).littleEndian
        let headerSampleRatePointer = UnsafeBufferPointer(start: &headerSampleRate, count: 1)
        header.append(headerSampleRatePointer)
        
        var byteRate = Int32(sampleRate * numChannels * bitsPerSample / 8).littleEndian
        let byteRatePointer = UnsafeBufferPointer(start: &byteRate, count: 1)
        header.append(byteRatePointer)
        
        var blockAlign = Int16(numChannels * bitsPerSample / 8).littleEndian
        let blockAlignPointer = UnsafeBufferPointer(start: &blockAlign, count: 1)
        header.append(blockAlignPointer)
        
        var headerBitsPerSample = Int16(bitsPerSample).littleEndian
        let headerBitsPerSamplePointer = UnsafeBufferPointer(start: &headerBitsPerSample, count: 1)
        header.append(headerBitsPerSamplePointer)
        
        // "data" sub-chunk
        let subchunk2ID = [UInt8]("data".utf8)
        header.append(subchunk2ID, count: 4)
        
        var subchunk2Size = Int32(pcmDataLength).littleEndian
        let subchunk2SizePointer = UnsafeBufferPointer(start: &subchunk2Size, count: 1)
        
        header.append(subchunk2SizePointer)
        
        return header
    }
}
Sega-Zero
  • 3,034
  • 2
  • 22
  • 46