Inside Macintosh: Sound Manager

| Previous | Chapter contents | Chapter top | Section top | Next |

Legacy Documentclose button

Important: Sound Input Manager is deprecated as of Mac OS X v10.5. For new audio development in Mac OS X, use Core Audio. See the Audio page in the ADC Reference Library.

Recording Sounds Directly From a Device

The Sound Input Manager provides a number of routines that you can use for low-level control over the recording process (such as the ability to intercept sound input data at interrupt time). You can open a sound input device and read data from it by calling these low-level Sound Input Manager routines. Several of those routines access information through a sound input parameter block, which is defined by the SPB data type:

TYPE SPB =
RECORD
    inRefNum:                   LongInt;        {reference number of input device}
    count:                      LongInt;        {number of bytes to record}
    milliseconds:               LongInt;        {number of milliseconds to record}
    bufferLength:               LongInt;        {length of buffer to record into}
    bufferPtr:                  Ptr;            {pointer to buffer to record into}
    completionRoutine:          ProcPtr;        {pointer to a completion routine}
    interruptRoutine:           ProcPtr;        {pointer to an interrupt routine}
    userLong:                   LongInt;        {for application's use}
    error:                      OSErr;          {error returned after recording}
    unused1:                    LongInt;        {reserved}
END;

The inRefNum field indicates the reference number of the sound input device from which the recording is to occur. You can obtain the reference number of the default sound input device by using the SPBOpenDevice function.

The count , milliseconds , and bufferLength fields jointly determine the length of recording. The count field indicates the number of bytes to record; the milliseconds field indicates the number of milliseconds to record; and the bufferLength field indicates the length in bytes of the buffer into which the recorded sound data is to be placed. If the count and milliseconds fields are not equivalent, then the field which specifies the longer recording time is used. If the buffer specified by the bufferLength field is shorter than this recording time, then the recording time is truncated so that the recorded data can fit into the buffer specified by the bufferPtr field. The Sound Input Manager provides two functions, SPBMilliSecondsToBytes and SPBBytesToMilliSeconds , that allow you to convert between byte and millisecond values.

After recording finishes, the count and milliseconds fields indicate the number of bytes and milliseconds actually recorded.

The completionRoutine and interruptRoutine fields allow your application to define a sound input completion routine and a sound input interrupt routine, respectively. More information on these routines is provided later in this section.

The userLong field contains a long integer that is provided for your application's own use. You can use this field, for instance, to pass a handle to an application-defined structure to the sound input completion or interrupt routine. Or, you can use this field to store the value of your application's A5 register, so that your sound input completion or interrupt routine can access your application's global variables. For more information on preserving the value of the A5 register, see the discussion of the SetA5 and SetCurrentA5 functions in the chapter "Memory Management Utilities" in Inside Macintosh: Memory .

The error field describes any errors that occur during the recording. This field contains a value greater than 0 while recording unless an error occurs, in which case it contains a value less than 0 that indicates an operating system error. Your application can poll this field to check on the status of an asynchronous recording. If recording terminates without an error, this field contains 0.

Listing 42 shows how to set up a sound parameter block and record synchronously using the SPBRecord function. This procedure takes one parameter, a handle to a block of memory in which the recorded sound data is to be stored. It is assumed that the block of memory is large enough to hold the sound to be recorded.

Listing 42 Recording directly from a sound input device

PROCEDURE MyRecordSnd (mySndH: Handle);
CONST
    kAsync = TRUE;
    kMiddleC = 60;
VAR
    mySPB:              SPB;            {a sound input parameter block}
    myInRefNum:         LongInt;        {device reference number}
    myBuffSize:         LongInt;        {size of buffer to record into}
    myHeadrLen:         Integer;        {length of sound header}
    myNumChans:         Integer;        {number of channels}
    mySampSize:         Integer;        {size of a sample}
    mySampRate:         Fixed;          {sample rate}
    myCompType:         OSType;         {compression type}
    myErr:              OSErr;
BEGIN
    {Open the default input device for reading and writing.}
    myErr := SPBOpenDevice('', siWritePermission, myInRefNum);

    IF myErr = noErr THEN
    BEGIN
        {Get current settings of sound input device.}
        MyGetDeviceSettings(myInRefNum, myNumChans, mySampRate,
                                    mySampSize, myCompType);

        {Set up handle to contain the 'snd ' resource header.}
        myErr := SetupSndHeader(mySndH, myNumChans, mySampRate,mySampSize,
                                            myCompType, kMiddleC, 0, myHeadrLen);

        {Leave room in buffer for the sound resource header.}
        myBuffSize := GetHandleSize(mySndH) - myHeadrLen;

        {Lock down the sound handle until the recording is over.}
        HLockHi(mySndH);

        {Set up the sound input parameter block.}
        WITH mySPB do
        BEGIN
            inRefNum := myInRefNum;                     {input device reference number}
            count := myBuffSize;                        {number of bytes to record}
            milliseconds := 0;                          {no milliseconds}
            bufferLength := myBuffSize;                 {length of buffer}
            bufferPtr := Ptr(ORD4(mySndH^) + myHeadrLen);
                                                        {put data after 'snd ' header}
            completionRoutine := NIL;                   {no completion routine}
            interruptRoutine := NIL;                    {no interrupt routine}
            userLong := 0;                              {no user data}
            error := noErr;                             {clear error field}
            unused1 := 0;                               {clear reserved field}
        END;

        {Record synchronously through the open sound input device.}
        myErr := SPBRecord(@mySPB, NOT kAsync);

        HUnlock(mySndH);                                {unlock the handle}

        {Indicate the number of bytes actually recorded.}
        myErr := SetupSndHeader(mySndH, myNumChans, mySampRate, mySampSize,
                                            myCompType, kMiddleC, mySPB.count,
                                            myHeadrLen);

        {Close the input device.}
        myErr := SPBCloseDevice(myInRefNum);
    END;
END;

The MyRecordSnd procedure defined in Listing 42 opens the default sound input device by using the SPBOpenDevice function. You can specify one of two values for the permission parameter of SPBOpenDevice :

CONST
    siReadPermission        = 0;    {open device for reading}
    siWritePermission       = 1;    {open device for reading/writing}

You must open a device for both reading and writing if you intend to use the SPBSetDeviceInfo function or the SPBRecord function. If SPBOpenDevice successfully opens the specified device for reading and writing, MyRecordSnd calls the  MyGetDeviceSettings procedure (defined in Listing 44 ). That procedure calls the Sound Input Manager function SPBGetDeviceInfo (explained in "Getting and Setting Sound Input Device Information" ) to determine the current number of channels, sample rate, sample size, and compression type in use by the device.

This information is then passed to the SetupSndHeader function, which sets up the handle mySndH with a sound header describing the current device settings. After doing this, MyRecordSnd sets up a sound input parameter block and calls the SPBRecord function to record a sound. Note that the handle must be locked during the recording because the parameter block contains a pointer to the input buffer. After the recording is done, MyRecordSnd once again calls the SetupSndHeader function to fill in the actual number of bytes recorded.

If the MyRecordSnd procedure defined in Listing 42 executes successfully, the handle mySndH points to a resource of type 'snd ' . Your application can then synchronously play the recorded sound, for example, by executing the following line of code:

myErr := SndPlay(NIL, mySndH, FALSE);

For more information on playing sounds your application has recorded, see the chapter "Sound Manager" in this book.

Defining a Sound Input Completion Routine

Defining a Sound Input Interrupt Routine


© 1999 Apple Computer, Inc.

Inside Macintosh: Sound Manager

| Previous | Chapter contents | Chapter top | Section top | Next |

Legacy Documentclose button

Important: Sound Input Manager is deprecated as of Mac OS X v10.5. For new audio development in Mac OS X, use Core Audio. See the Audio page in the ADC Reference Library.