OSDN Git Service

0.2.1
[eliscolors/main.git] / ElisAudioWriter.m
1 //
2 //  ElisAudioWriter.m
3 //  Elis Colors
4 //
5 //  Created by 柳 on 09/10/04.
6 //  Copyright 2009 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "ElisAudioWriter.h"
10
11 #define CURRENT_TIME() inFileFormat.mSampleRate
12
13 @implementation ElisAudioWriter
14
15 - (id)initWithLayer:(ElisLayer*)l
16 {
17     layer = l;
18     return self;
19 }
20
21 - (void)writeToFile:(NSString*)outPath
22 {
23     
24     NSString* inPath;
25     
26     inPath = [[layer media] path];
27     
28     //一度に変換するフレーム数
29     UInt32 convertFrames = 256; // 1/60フレームがこれくらいのはず。
30     
31     //変数の宣言
32     OSStatus err = noErr;
33     UInt32 size;
34     ExtAudioFileRef inAudioFileRef = NULL;
35     ExtAudioFileRef outAudioFileRef = NULL;
36     AudioStreamBasicDescription inFileFormat, ioClientFormat, outFileFormat;
37     void *ioData = NULL;
38     
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;
44     
45     //読み込み側のオーディオファイルからフォーマットを取得する
46     size = sizeof(ioClientFormat);
47     err = ExtAudioFileGetProperty(
48                                   inAudioFileRef, kExtAudioFileProperty_FileDataFormat, 
49                                   &size, &inFileFormat);
50     if (err != noErr) goto catchErr;
51     
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];
58     
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;
71     
72     // 書き出しするファイルを削除しておく。
73     [[NSFileManager defaultManager] removeFileAtPath:outPath handler:nil];
74     
75     //書き出し側のオーディオファイルを作成する
76     err = ExtAudioFileCreateWithURL(
77                                     (CFURLRef)outUrl, kAudioFileWAVEType, &outFileFormat, 
78                                     NULL, 0, &outAudioFileRef);
79     if (err != noErr) goto catchErr;
80     
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;
92     
93     size = sizeof(ioClientFormat);
94     err = ExtAudioFileSetProperty(
95                                   outAudioFileRef, kExtAudioFileProperty_ClientDataFormat, 
96                                   size, &ioClientFormat);
97     if (err != noErr) goto catchErr;
98     
99     size = sizeof(ioClientFormat);
100     err = ExtAudioFileSetProperty(
101                                   inAudioFileRef, kExtAudioFileProperty_ClientDataFormat, 
102                                   size, &ioClientFormat);
103     if (err != noErr) goto catchErr;
104     
105     //オーディオデータの読み書きに使用するメモリ領域を確保する
106     UInt32 allocByteSize = convertFrames * ioClientFormat.mBytesPerFrame;
107     ioData = malloc(allocByteSize);
108     if (!ioData) {
109         err = 1002;
110         goto catchErr;
111     }
112     memset(ioData, 0, allocByteSize);
113     
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;
120     
121     // オフセットの分だけずらす。
122     int f, startFrame, silentFrame, endFrame;
123     QTTime t = [layer plusOffsetTime:QTZeroTime];
124     startFrame = (float)t.timeValue/t.timeScale * inFileFormat.mSampleRate;
125     
126     t = [layer mapping].time;
127     silentFrame = (float)t.timeValue/t.timeScale * inFileFormat.mSampleRate;
128     
129     t = [layer mapping].duration;
130     endFrame = (float)t.timeValue/t.timeScale * inFileFormat.mSampleRate;
131     
132     ExtAudioFileSeek(inAudioFileRef, startFrame);
133     
134     //オーディオデータをコピーする
135     for(f = 0; f < endFrame; f += convertFrames) {
136         //フレーム数とデータサイズを設定する
137         UInt32 frames = convertFrames;
138         ioList.mBuffers[0].mDataByteSize = allocByteSize;
139         
140         //読み込み側のオーディオファイルからオーディオデータを読み込む
141         if(f > silentFrame){
142             err = ExtAudioFileRead(inAudioFileRef, &frames, &ioList);
143             if (err != noErr) goto catchErr;
144             
145             int i, offset;
146             float src;
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);
152             }
153         }
154         
155         //最後まで読み込んだら終了
156         if (frames == 0) break;
157         
158         //書き込み側のオーディオファイルへ書き込む
159         err = ExtAudioFileWrite(outAudioFileRef, frames, &ioList);
160         if (err != noErr) goto catchErr;
161     }
162     
163     NSLog(@"complete");
164     
165     
166 catchErr:
167     
168     if (err != noErr) NSLog(@"err = %ld", err);
169     
170     //解放する
171     if (ioData) free(ioData);
172     if (inAudioFileRef) ExtAudioFileDispose(inAudioFileRef);
173     if (outAudioFileRef) ExtAudioFileDispose(outAudioFileRef);
174     
175     return 0;
176 }
177
178 @end