Created
January 3, 2012 17:19
-
-
Save wader/1555889 to your computer and use it in GitHub Desktop.
Wav merge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // a bit hackish way of merging two wav files, assumes raw samples. | |
| #import <Foundation/Foundation.h> | |
| #define RIFF_ID 0x52494646 // "RIFF" | |
| #define RIFF_FMT_ID 0x666d7420 // "fmt " | |
| #define RIFF_DATA_ID 0x64617461 // "data" | |
| typedef struct riffChunkHeader { | |
| UInt32 rsc_id; // big endian | |
| UInt32 rsc_size; // little endian | |
| } riffChunkHeader_t; | |
| NSData *extractRiffChunk(NSData *riffData, UInt32 extractId, BOOL extractOnlyData); | |
| NSData *extractRiffChunkAll(NSData *riffData, UInt32 extractId); | |
| NSData *extractRiffChunkData(NSData *riffData, UInt32 extractId); | |
| NSData *extractRiffChunk(NSData *riffData, UInt32 extractId, BOOL extractOnlyData) { | |
| NSUInteger offset = 0; | |
| while (([riffData length] - offset) >= sizeof(riffChunkHeader_t)) { | |
| NSData *riffChunkRange = [riffData subdataWithRange: | |
| NSMakeRange(offset, sizeof(riffChunkHeader_t))]; | |
| const riffChunkHeader_t *riffChunk = [riffChunkRange bytes]; | |
| UInt32 riffId = NSSwapBigIntToHost(riffChunk->rsc_id); | |
| NSUInteger riffSize = NSSwapLittleIntToHost(riffChunk->rsc_size); | |
| // treat RIFF chunk as a subchunk containing format | |
| if (riffId == RIFF_ID) { | |
| riffSize = 4; | |
| } | |
| if (riffId != extractId) { | |
| offset += sizeof(riffChunkHeader_t) + riffSize; | |
| continue; | |
| } | |
| NSUInteger len; | |
| if (extractOnlyData) { | |
| offset += sizeof(riffChunkHeader_t); | |
| len = riffSize; | |
| } else { | |
| len = sizeof(riffChunkHeader_t) + riffSize; | |
| } | |
| if (([riffData length] - offset) < riffSize) { | |
| break; | |
| } | |
| return [riffData subdataWithRange:NSMakeRange(offset, len)]; | |
| } | |
| return nil; | |
| } | |
| NSData *extractRiffChunkAll(NSData *riffData, UInt32 extractId) { | |
| return extractRiffChunk(riffData, extractId, NO); | |
| } | |
| NSData *extractRiffChunkData(NSData *riffData, UInt32 extractId) { | |
| return extractRiffChunk(riffData, extractId, YES); | |
| } | |
| NSData *mergeWavFiles(NSData *wavData1, NSData *wavData2); | |
| NSData *mergeWavFiles(NSData *wavData1, NSData *wavData2) { | |
| NSMutableData *riffAll = [[extractRiffChunkAll(wavData1, RIFF_ID) | |
| mutableCopy] | |
| autorelease]; | |
| NSData *fmtAll = extractRiffChunkAll(wavData1, RIFF_FMT_ID); | |
| NSData *file1Data = extractRiffChunkData(wavData1, RIFF_DATA_ID); | |
| NSData *file2Data = extractRiffChunkData(wavData2, RIFF_DATA_ID); | |
| riffChunkHeader_t riffDataSubChunk; | |
| riffDataSubChunk.rsc_id = NSSwapHostIntToBig(RIFF_DATA_ID); | |
| riffDataSubChunk.rsc_size = NSSwapHostIntToLittle((UInt32)[file1Data length] + | |
| (UInt32)[file2Data length]); | |
| NSData *dataHeader = [NSData dataWithBytes:&riffDataSubChunk | |
| length:sizeof(riffDataSubChunk)]; | |
| riffChunkHeader_t *riffChunk = [riffAll mutableBytes]; | |
| riffChunk->rsc_size = NSSwapHostIntToLittle(sizeof(riffChunkHeader_t) + | |
| (UInt32)[fmtAll length] + | |
| (UInt32)[dataHeader length] + | |
| (UInt32)[file1Data length] + | |
| (UInt32)[file2Data length]); | |
| NSMutableData *mergedWav = [NSMutableData data]; | |
| [mergedWav appendData:riffAll]; | |
| [mergedWav appendData:fmtAll]; | |
| [mergedWav appendData:dataHeader]; | |
| [mergedWav appendData:file1Data]; | |
| [mergedWav appendData:file2Data]; | |
| return mergedWav; | |
| } | |
| int main (int argc, const char * argv[]) | |
| { | |
| @autoreleasepool { | |
| [mergeWavFiles([NSData dataWithContentsOfURL: | |
| [NSURL URLWithString:@"file:///path/to/test1.wav"]], | |
| [NSData dataWithContentsOfURL: | |
| [NSURL URLWithString:@"file:///path/to/test2.wav"]]) | |
| writeToURL:[NSURL URLWithString:@"file:///path/to/merged.wav"] | |
| atomically:YES]; | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment