Mac OS X v10.3.x上でCoreAudioと共にNSSoundを使う

原文 Technical Q&A QA1394: Using NSSound with CoreAudio on Mac OS 10.3.x http://developer.apple.com/qa/qa2005/qa1394.html

質問: Mac OS X v10.3.x上でCoreAudioと共にNSSoundを使う場合、なぜIOProcコールバックでNULLデータを渡さなければならないのでしょうか。

回答: アプリケーションの種類によっては、Application KitフレームワークのNSSoundとCore Audioを同一アプリケーション内で同居させた方が便利なことがあります。 このような場合開発者は、NSSoundがCore AudioのHAL(ハードウェア抽象化層)のIOProcとデータの受け渡しをしている可能性を考慮しなければなりません。

MacOS 10.3.xシステム上で、Core AudioフレームワークのIOProcコールバックと同じプロセスでNSSoundを使う場合、そのIOProcコールバックの入力バッファをNULLにする事が要求されます。 このバグは、NSSoundが音声出力に使用する装置ーつまり、デフォルトの音声出力装置ーにCore AudioのIOProcを加えるようなアプリケーションに、影響を与えます。 オーディオ装置にCore Audio IOProcを加える前にNSSoundを呼び出すアプリケーションでは、IOProcの入力バッファはNULLになっています。

この問題を回避するには、一切のNSSound呼び出しの前に、そのプロセスがAudioDeviceAddIOProcを呼び出す必要があります。

Listing 1: 問題有りのサンプル

#import <Cocoa/Cocoa.h>
#import <CoreAudio/CoreAudio.h>
 
OSStatus recordIOProc ( AudioDeviceID inDevice,
                        const AudioTimeStamp* inNow,
                        const AudioBufferList* inInputData,
                        const AudioTimeStamp* inInputTime,
                        AudioBufferList* outOutputData,
                        const AudioTimeStamp* inOutputTime,
                        void* inClientData )
{
    if ( inInputData )
    {
        if ( inInputData->mBuffers[0].mData == NULL )
            NSLog (@"CoreAudio IOProcの入力バッファはNULL");
    }
 
    return noErr;
}
 
int main()
{
    NSAutoreleasePool * pool = [NSAutoreleasePool new];
    AudioDeviceID device;
 
    UInt32 theSize = sizeof(AudioDeviceID);
    verify_noerr( AudioHardwareGetProperty ( kAudioHardwarePropertyDefaultInputDevice, &theSize, & device ) );
 
    NSSound *sound = [[NSSound alloc] initWithContentsOfFile:
                                  @"/System/Library/Sounds/Submarine.aiff" byReference:NO];
   [sound play];
 
    verify_noerr( AudioDeviceAddIOProc ( device, recordIOProc, NULL ) );
    verify_noerr( AudioDeviceStart ( device, recordIOProc ) );
 
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
 
    verify_noerr( AudioDeviceStop ( device, recordIOProc ) );
    verify_noerr( AudioDeviceRemoveIOProc ( device, recordIOProc ) );
 
    [sound release];
 
    [pool release];
    return 0;
}

上のサンプルコードを実行すると、標準出力(stdout)に何回も"CoreAudio IOProcの入力バッファはNULL"と表示される事がわかります。

この問題を回避するには、NSSound呼び出しの前に、AudioDeviceAddIOProcを呼び出します。 上記サンプルの問題修正版を以下に掲載します: **Listing 2:** 問題を修正したサンプル #import #import OSStatus recordIOProc ( AudioDeviceID inDevice, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, const AudioTimeStamp* inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* inClientData ) { if ( inInputData ) { if ( inInputData->mBuffers[0].mData == NULL ) NSLog (@"CoreAudio IOProcの入力バッファはNULL"); } return noErr; } int main() { NSAutoreleasePool * pool = [NSAutoreleasePool new]; AudioDeviceID device; UInt32 theSize = sizeof(AudioDeviceID); verify_noerr( AudioHardwareGetProperty ( kAudioHardwarePropertyDefaultInputDevice, &theSize, & device ) ); // NSSoundを使う「前」に呼ぶ verify_noerr( AudioDeviceAddIOProc ( device, recordIOProc, NULL ) ); NSSound *sound = [[NSSound alloc] initWithContentsOfFile: @"/System/Library/Sounds/Submarine.aiff" byReference:NO]; [sound play]; verify_noerr( AudioDeviceStart ( device, recordIOProc ) ); [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]]; verify_noerr( AudioDeviceStop ( device, recordIOProc ) ); verify_noerr( AudioDeviceRemoveIOProc ( device, recordIOProc ) ); [sound release]; [pool release]; return 0; } ここで行った変更は、AudioDeviceAddIOProc呼び出しをNSSound呼び出しの前に移動しただけだという点にご注意下さい。 このサンプルコードを実行しても、recordIOProcが"CoreAudio IOProcの入力バッファはNULL"と表示することはありません。つまりこれは、 Notice that the only change that's been made here is that we've moved the AudioDeviceAddIOProc call to before the NSSound calls. When running this sample code, recordIOProc will not print out the string "CoreAudio IOProc is being given NULL input buffers", indicating that it is receiving valid input buffers.

Note that it is not necessary to call AudioDeviceStart before any calls to NSSound. It is only necessary to call AudioDeviceAddIOProc.

 
翻訳文章/オーディオ/technical_q_a/qa1394_mac_os_x_v10.3.x上でcoreaudioと共にnssoundを使う.txt · 最終更新: 2007/05/31 20:20 (外部編集)
 
特に明示されていない限り、本Wikiの内容は次のライセンスに従います:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki