5 // Created by 柳 on 09/10/04.
6 // Copyright 2009 __MyCompanyName__. All rights reserved.
9 #import "ElisAudioWriter.h"
11 #define CURRENT_TIME() inFileFormat.mSampleRate
13 @implementation ElisAudioWriter
15 - (id)initWithLayer:(ElisLayer*)l
21 - (void)writeToFile:(NSString*)outPath
26 inPath = [[layer media] path];
29 UInt32 convertFrames = 256; // 1/60フレームがこれくらいのはず。
34 ExtAudioFileRef inAudioFileRef = NULL;
35 ExtAudioFileRef outAudioFileRef = NULL;
36 AudioStreamBasicDescription inFileFormat, ioClientFormat, outFileFormat;
39 //読み込み側のオーディオファイルを開く(2008/6/26修正)
40 //NSURL *inUrl = [NSURL URLWithString:inPath];
41 NSURL *inUrl = [NSURL fileURLWithPath:inPath];
42 err = ExtAudioFileOpenURL((CFURLRef)inUrl, &inAudioFileRef);
43 if (err != noErr) goto catchErr;
45 //読み込み側のオーディオファイルからフォーマットを取得する
46 size = sizeof(ioClientFormat);
47 err = ExtAudioFileGetProperty(
48 inAudioFileRef, kExtAudioFileProperty_FileDataFormat,
49 &size, &inFileFormat);
50 if (err != noErr) goto catchErr;
52 //書き出し側のオーディオファイルのパスを作成する(2008/6/26修正)
53 // NSString *outPath =
54 // [[inPath stringByDeletingPathExtension]
55 // stringByAppendingString:@"-export.wav"];
56 //NSURL *outUrl = [NSURL URLWithString:outPath];
57 NSURL *outUrl = [NSURL fileURLWithPath:outPath];
59 //書き出し側のオーディオファイルのフォーマットを作成する
60 outFileFormat.mSampleRate = 44100;
61 outFileFormat.mFormatID = kAudioFormatLinearPCM;
62 outFileFormat.mFormatFlags =
63 kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
64 outFileFormat.mBitsPerChannel = 16;
65 outFileFormat.mChannelsPerFrame = inFileFormat.mChannelsPerFrame;
66 outFileFormat.mFramesPerPacket = 1;
67 outFileFormat.mBytesPerFrame =
68 outFileFormat.mBitsPerChannel / 8 * outFileFormat.mChannelsPerFrame;
69 outFileFormat.mBytesPerPacket =
70 outFileFormat.mBytesPerFrame * outFileFormat.mFramesPerPacket;
73 [[NSFileManager defaultManager] removeFileAtPath:outPath handler:nil];
75 //書き出し側のオーディオファイルを作成する
76 err = ExtAudioFileCreateWithURL(
77 (CFURLRef)outUrl, kAudioFileWAVEType, &outFileFormat,
78 NULL, 0, &outAudioFileRef);
79 if (err != noErr) goto catchErr;
81 //読み書き両方のクライアントフォーマットを設定する
82 ioClientFormat.mSampleRate = inFileFormat.mSampleRate;
83 ioClientFormat.mFormatID = kAudioFormatLinearPCM;
84 ioClientFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
85 ioClientFormat.mBitsPerChannel = 32;
86 ioClientFormat.mChannelsPerFrame = inFileFormat.mChannelsPerFrame;
87 ioClientFormat.mFramesPerPacket = 1;
88 ioClientFormat.mBytesPerFrame =
89 ioClientFormat.mBitsPerChannel / 8 * ioClientFormat.mChannelsPerFrame;
90 ioClientFormat.mBytesPerPacket =
91 ioClientFormat.mBytesPerFrame * ioClientFormat.mFramesPerPacket;
93 size = sizeof(ioClientFormat);
94 err = ExtAudioFileSetProperty(
95 outAudioFileRef, kExtAudioFileProperty_ClientDataFormat,
96 size, &ioClientFormat);
97 if (err != noErr) goto catchErr;
99 size = sizeof(ioClientFormat);
100 err = ExtAudioFileSetProperty(
101 inAudioFileRef, kExtAudioFileProperty_ClientDataFormat,
102 size, &ioClientFormat);
103 if (err != noErr) goto catchErr;
105 //オーディオデータの読み書きに使用するメモリ領域を確保する
106 UInt32 allocByteSize = convertFrames * ioClientFormat.mBytesPerFrame;
107 ioData = malloc(allocByteSize);
112 memset(ioData, 0, allocByteSize);
114 //オーディオデータの読み書きに使用するAudioBufferListを作成する
115 AudioBufferList ioList;
116 ioList.mNumberBuffers = 1;
117 ioList.mBuffers[0].mNumberChannels = ioClientFormat.mChannelsPerFrame;
118 ioList.mBuffers[0].mDataByteSize = allocByteSize;
119 ioList.mBuffers[0].mData = ioData;
122 int f, startFrame, silentFrame, endFrame;
123 QTTime t = [layer plusOffsetTime:QTZeroTime];
124 startFrame = (float)t.timeValue/t.timeScale * inFileFormat.mSampleRate;
126 t = [layer mapping].time;
127 silentFrame = (float)t.timeValue/t.timeScale * inFileFormat.mSampleRate;
129 t = [layer mapping].duration;
130 endFrame = (float)t.timeValue/t.timeScale * inFileFormat.mSampleRate;
132 ExtAudioFileSeek(inAudioFileRef, startFrame);
135 for(f = 0; f < endFrame; f += convertFrames) {
137 UInt32 frames = convertFrames;
138 ioList.mBuffers[0].mDataByteSize = allocByteSize;
140 //読み込み側のオーディオファイルからオーディオデータを読み込む
142 err = ExtAudioFileRead(inAudioFileRef, &frames, &ioList);
143 if (err != noErr) goto catchErr;
147 // offset = ioList.mBuffers[0].mDataByteSize/frames;
148 float v = [layer getVolumeForTime:QTMakeTime(f, inFileFormat.mSampleRate)];
149 for(i = 0; i < ioList.mBuffers[0].mDataByteSize; i += 4){
150 src = *(float*)(ioList.mBuffers[0].mData + i);
151 *(float*)(ioList.mBuffers[0].mData + i) = (float)(src*v);
156 if (frames == 0) break;
158 //書き込み側のオーディオファイルへ書き込む
159 err = ExtAudioFileWrite(outAudioFileRef, frames, &ioList);
160 if (err != noErr) goto catchErr;
168 if (err != noErr) NSLog(@"err = %ld", err);
171 if (ioData) free(ioData);
172 if (inAudioFileRef) ExtAudioFileDispose(inAudioFileRef);
173 if (outAudioFileRef) ExtAudioFileDispose(outAudioFileRef);