1

openframeworksとこのウェブサイトhttp://atastypixel.com/blog/using-remoteio-audio-unitの助けを借りて Audio Units を使用して、マイクからオーディオ ファイルにオーディオを正常に録音しました。

ファイルをオーディオ ユニットにストリーミングして、オーディオを再生できるようにしたいと考えています。Play an audio file using RemoteIO and Audio Unitによると、ExtAudioFileOpenURL と ExtAudioFileRead を使用できます。しかし、バッファ内のオーディオ データを再生するにはどうすればよいでしょうか。

これは私が現在持っているものです:

static OSStatus setupAudioFileRead() {
    //construct the file destination URL
    CFURLRef destinationURL = audioSystemFileURL();
    OSStatus status = ExtAudioFileOpenURL(destinationURL, &audioFileRef);
    CFRelease(destinationURL);

    if (checkStatus(status)) { ofLog(OF_LOG_ERROR, "ofxiPhoneSoundStream: Couldn't open file to read"); return status; }

    while( TRUE ) {
        // Try to fill the buffer to capacity.
        UInt32 framesRead = 8000;
        status = ExtAudioFileRead( audioFileRef, &framesRead, &inputBufferList );

        // error check
        if( checkStatus(status) ) { break; }

        // 0 frames read means EOF.
        if( framesRead == 0 ) { break; }

        //play audio???
    }

    return noErr;
}
4

3 に答える 3

0

これは、Tasty Pixel ブログで言及されているオーディオ ユニットを利用する比較的単純なアプローチです。録音コールバックでは、マイクからのデータでバッファを埋める代わりに、ExtAudioFileRead を使用してファイルからのデータでバッファを埋めることができます。以下に例を貼り付けてみます。これは .caf ファイルに対してのみ機能することに注意してください。

start メソッドで readAudio または initAudioFile 関数を呼び出します。これは、ファイルに関するすべての情報を取得するだけのものです。

- (void) start {
readAudio();
OSStatus status = AudioOutputUnitStart(audioUnit);
checkStatus(status);
}

readAudio メソッドで、オーディオ ファイル参照をそのように初期化します。

ExtAudioFileRef fileRef;

void readAudio() {
NSString * name = @"AudioFile";
NSString * source = [[NSBundle mainBundle] pathForResource:name ofType:@"caf"];
const char * cString = [source cStringUsingEncoding:NSASCIIStringEncoding];
CFStringRef str = CFStringCreateWithCString(NULL, cString, kCFStringEncodingMacRoman);
CFURLRef inputFileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, str, kCFURLPOSIXPathStyle, false);

AudioFileID fileID;
OSStatus err = AudioFileOpenURL(inputFileURL, kAudioFileReadPermission, 0, &fileID);
CheckError(err, "AudioFileOpenURL");


err = ExtAudioFileOpenURL(inputFileURL, &fileRef);
CheckError(err, "ExtAudioFileOpenURL");

err = ExtAudioFileSetProperty(fileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &audioFormat);
CheckError(err, "ExtAudioFileSetProperty");
}

オーディオ データが手元にあるので、次のステップは非常に簡単です。recordingCallback では、マイクの代わりにファイルからデータを読み取ります。

static OSStatus recordingCallback(void *inRefCon,
                              AudioUnitRenderActionFlags *ioActionFlags,
                              const AudioTimeStamp *inTimeStamp,
                              UInt32 inBusNumber,
                              UInt32 inNumberFrames,
                              AudioBufferList *ioData) {

// Because of the way our audio format (setup below) is chosen:
// we only need 1 buffer, since it is mono
// Samples are 16 bits = 2 bytes.
// 1 frame includes only 1 sample

AudioBuffer buffer;

buffer.mNumberChannels = 1;
buffer.mDataByteSize = inNumberFrames * 2;
buffer.mData = malloc( inNumberFrames * 2 );

// Put buffer in a AudioBufferList
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0] = buffer;

// Then:
// Obtain recorded samples
OSStatus err = ExtAudioFileRead(fileRef, &inNumberFrames, &bufferList);

// Now, we have the samples we just read sitting in buffers in bufferList
// Process the new data
[iosAudio processAudio:&bufferList];

// release the malloc'ed data in the buffer we created earlier
free(bufferList.mBuffers[0].mData);

return noErr;
}

これは私にとってはうまくいきました。

于 2015-05-14T00:57:21.930 に答える
0

基本的には、 1. RemoteIO ユニットを作成します (RemoteIO の作成方法については、参考文献を参照してください)。

  1. オーディオ ファイルを読み取り、ファイル内のオーディオ データを出力ユニット (手順 1 で作成した RemoteIO ユニットなど) に提供する専用のオーディオ ユニットである FilePlayer オーディオ ユニットを作成します。実際に FilePlayer を使用するには、多くの設定 (どのファイルを再生するか、ファイルのどの部分を再生するかなど) を it 上で実行する必要があります。

  2. RemoteIO ユニットの kAudioUnitProperty_SetRenderCallback および kAudioUnitProperty_StreamFormat プロパティを設定します。最初のプロパティは基本的に、RemoteIO ユニットがオーディオ データをプルして再生するコールバック関数です。2 番目のプロパティは、FilePlayer でサポートされている StreamFormat に従って設定する必要があります。これは、FilePlayer で呼び出された get-property 関数から派生できます。

  3. 手順 3 でコールバック セットを定義します。ここで最も重要なことは、FilePlayer で AudioUnitRender() を呼び出す必要があるコールバックによって提供されるバッファにレンダリングするよう FilePlayer に要求することです。

  4. 最後に RemoteIO ユニットを起動してファイルを再生します。

上記は、iOS でオーディオ ユニットを使用してファイルを再生するための基本的な手順の概要です。詳細については、Chris Adamson と Kevin Avila のLearning Core Audioを参照してください。

于 2013-10-16T02:05:24.837 に答える
0

この作者から: http://atastypixel.com/blog/using-remoteio-audio-unit/、下にスクロールして PLAYBACK セクションまで移動したら、次のようにしてみてください:

static OSStatus playbackCallback(void *inRefCon, 
                                  AudioUnitRenderActionFlags *ioActionFlags, 
                                  const AudioTimeStamp *inTimeStamp, 
                                  UInt32 inBusNumber, 
                                  UInt32 inNumberFrames, 
                                  AudioBufferList *ioData) {    
    // Notes: ioData contains buffers (may be more than one!)
    // Fill them up as much as you can. Remember to set the size value in each buffer to match how
    // much data is in the buffer.

for (int i=0; i < ioData->mNumberBuffers; i++) 
{ 
    AudioBuffer buffer = ioData->mBuffers[i];
    // copy from your whatever buffer data to output buffer
    UInt32 size = min(buffer.mDataByteSize, your buffer.size); 
    memcpy(buffer.mData, your buffer, size);
    buffer.mDataByteSize = size; // indicate how much data we wrote in the buffer

    // To test if your Audio Unit setup is working - comment out the three 
    // lines above and uncomment the for loop below to hear random noise  
    /*
    UInt16 *frameBuffer = buffer.mData;
    for (int j = 0; j < inNumberFrames; j++) {
        frameBuffer[j] = rand();
    }
    */
}
return noErr;
}

MIC からファイルに録音して再生するだけの場合は、おそらく Apple のSpeakhereサンプルの方がすぐに使用できます。

于 2012-08-02T22:49:34.323 に答える