| 
     
|  | Starting
         with Mac OS 9.0 there is a new way of playing CD audio -- digitally. Pure digital data is read from the CD, played
         through the Sound Manager as a PCM (Pulse Code Modulation -- standard uncompressed audio) data stream, and then
         sent out to the speakers (where your ears require that it be
         converted back to an analog signal). This Technote describes how an application uses the
         new digital CD audio support and what a CD or DVD driver
         needs to do to support playing audio digitally.  Updated: [Apr 3 2000] |  
 
 
 
 
 
 The way it wasFor as long as the Macintosh has had a built in
         CD-ROM, the audio has been played as an analog sound stream.
         The CD-ROM drive would output analog sound, just like a
         microphone, and the Mac would record that audio, optionally
         passing it through to the speakers (play through). A diagram of the flow of audio data (from the
         CD-ROM only for simplification) looks like this:   The audio data was read by the CD-ROM drive and
         converted to analog audio inside the CD-ROM drive. From
         there the analog audio would go to the sound hardware on the
         Macintosh. It would then be converted back to digital data
         and given to the Sound Manager. The Sound Manager would then
         pass the audio to any application that was recording the CD
         audio input source. If play through was turned on, the sound
         hardware would automatically route the analog sound back out
         to the speakers (or headphones), requiring no CPU
         intervention or overhead to hear the audio. The multiple
         conversions of the audio introduced the possibility of noise
         and reduced sound quality as well as making it difficult to
         precisely know, to a sample accuracy, what was being
         played. That has all changed with Mac OS 9.0. Back to top 
 
 The way it is nowStarting with Mac OS 9.0, on all ROM-in-RAM Macs
         (currently the iMac, iMac DV, iBook, Blue & White Power
         Macintosh G3, Power Macintosh G4, and Bronze Keyboard PowerBook
         G3 Series) there is a new sound input device called "Internal CD." When
         Internal CD is the selected input source, the Macintosh
         reads digital data directly from the CD and plays it as 
         high-quality digital audio from CD using standard Sound Input
         Manager recording calls. However, the Internal CD input
         driver does not have to be selected to allow the user listen
         to the CD, it only has to be selected to record from.   Instead of using the digital to analog converters
         built into the CD-ROM drive (which may be of questionable
         quality to audio purists), the audio is read as digital
         data, much like a normal file would be read off of a CD.
         This digital audio is then passed to the Sound Manager which
         plays it, as it would play any sound. This allows the sound to be played by the built-in
         sound hardware and the built-in speakers of the Macintosh,
         or out via some other hardware, such as USB speakers.
         Previously it was not possible for the internal audio CD to
         be played out via third-party hardware. The flow of audio data now looks like this:   However, this also means that the CPU is now
         running code that plays the audio. A very minor performance
         penalty is extracted for this new functionality. The
         measured statistics are about 0.5% CPU usage on a PowerBook
         G3 300MHz when the sound output setting is set to 44.1 kHz.
         This number doesn't include the cost of the Sound Manager
         sound channel which is needed for the sound output. Back to top 
 
 How your application needs to changeThere is no longer an option of selecting the
         internal CD from the Built-in input driver. If the user's
         CPU is able to support digital CD audio the option of doing
         it the old analog way has been removed for a consistent user
         interface between different Macintoshes. If you would like to give the users of your
         application the ability to record digital CD audio using the
         new Internal CD input source, you will have to choose it as
         the recording source. It is a completely different sound
         input driver, not a different input source of the Built-in
         sound input device. You will need some method of selecting
         different input sources because you cannot assume that it
         will be the default input device. Apple does not recommend that you have the
         user use the Sound control panel to change the default input
         source unless the user wants a global change. Typically this
         is the not the case, as only one application wants to record
         from the Internal CD input source -- most applications
         will want to record from the microphone or sound in input.
         Therefore having the user change the system wide behavior is
         the wrong thing to do. Having your own interface element for this is the
         preferred method for changing all sound settings in your
         application. The proper way to choose the Internal CD input
         source is to construct a list of all sound input drivers
         (using repeated calls to SPBGetIndexedDevice)
         to populate a menu or a list. The application should store
         these settings in its preferences and configure the sound
         input driver and sound output component accordingly each
         time the application starts. Do not have the user set
         these settings in the Sound control and rely on them always
         being the default sound settings. There are a few key points that should be pointed
         out regarding the Internal CD input source: 
            Because it is a separate input device, the user can
            record from the microphone in one application (for
            instance, Speech Recognition), and listen to CD audio at
            the same time.The Internal CD input device will be busy when an
            application is recording from the CD. Be prepared to deal
            with this gracefully. It will not be busy when it
            is just playing a CD.Play through is always on. It is hoped that once most
            applications are updated to be able to deal with not
            having the siPlayThruOnOffselector
            supported that it will be removed. For now you should
            update your code to be able to deal with not being able
            to check or set the play through setting of an input
            source. Remember, thesiPlayThruOnOffselector is optional, so not all input devices support
            it. Back to top 
 
 How your CD/DVD driver needs to changeDevelopers of CD or DVD drivers may wish to support
         the new Internal CD input driver. To do this the driver
         needs to be updated to call some functions in the Internal
         CD PPC code fragment. Calling these functions from 68K code
         is not supported. If you wish to do that, you are squarely
         in unsupported territory - watch your step. These functions are called by the CD/DVD driver and
         are how digital audio is passed from the driver to the
         Internal CD driver when the CD/DVD driver gets an
         AudioPlaycontrol call. 
 
 
| Note:The term 'frame' in DigitalCDSound.h refers to a
Sample Frame as defined in Sound Manager
terminology, in this case a 4-byte sample, stereo,
16-bit per channel.
 In CD terminology, a 'frame' is defined as the
smallest addressable unit which is 1/75th of a
second, or 2352 bytes, or 588 stereo 16-bit per
channel samples. This technical note refers to a CD
'frame' as a 'block'. Sound Manager Reference:
Sampled-Sound
Data |  
 
 The exported functions of the DigitalCDSoundLib
         are: 
 
 
| 
typedef void (*ReadMoreCDAudioProcPtr)(SInt32 refCon);
typedef STACK_UPP_TYPE(ReadMoreCDAudioProcPtr) ReadMoreCDAudioUPP;
void    CDSoundMain( CDSoundInfoTable *infoTable, SInt32 drvrRef );
OSErr   SetupSound( UInt32 bytesInRingBuffer,
                    ReadMoreCDAudioUPP readMoreCDUPP,
                    SInt32 refCon,
                    Component outputDevice,
                    UInt32 numMarkers );
OSErr   TeardownSound( void );
void    CDSoundTerminate ( void );
void    StartSound( void );
void    StopSound( void );
void    PlayRing( void );
void    PauseRing( void );
SInt32  RingBytesAvailable( void );
void    WriteAudioToRing( SInt16 *newData, UInt32 numFrames );
void    StitchAudioIntoRing( Ptr wholeBuff,
                             UInt32 buffFrames,
                             UInt32 overlapFrames );
void    InvalidateRingBuffer( void );
SInt32  GetVolume( void );
OSErr   SetVolume( SInt32 volume );
OSErr   Set3DSoundOn( void );
OSErr   Set3DSoundOff( void );
void    SetTrackMarker( UInt32 marker );
void    GetCurrentTrackMarker( UInt32 *marker,
                               UInt32 *framesBeyondMarker ); |  
 The usage, and general ordering, of these routines
         is as follows: 
            Call CDSoundMainwhich will install the
            "Internal CD" sound input driver and create other needed
            internal structures.Pass a validCDSoundInfoTablewith theversionNumberfield set to 1. FordrvrRef, pass in the reference number of the
            driver that will be reading the digital audio. Ignore the
            values of the fields inCDSoundInfoTablewhenCDSoundMainreturns. You cannot call
            this function at interrupt time, call it only at task
            time.Call SetupSound. This allocates all
            necessary data structures. Pass this function the size in
            bytes of the ring buffer you want to use. Also pass a
            pointer to theUPPfor theReadMoreCDAudiofunction, and an optionalrefConthat will be passed to theReadMoreCDAudiofunction. The second to the
            last parameter contains the component reference of an
            output device to use. Set it tonilto use
            the default output device. The last parameter contains
            the number of track markers to allocate. This must be
            called at task level, and will returncontrolErrif the current execution level is
            not task level. 
 
 
| Note:
 SetupSoundcan return any of a
         number of errors due to conditions such as being out of
         memory, incorrect hardware, etc. Be prepared to deal with
         errors. |  
 
 
            Start reading audio CD data.Call StartSound. This will start the
            output running. Don't worry, the user won't hear anything
            until you put some data into the ring buffer. This
            function cannot be called at interrupt time, it must be
            called at task time.Once a CD read completes, call
            WriteAudioToRingorStitchAudioIntoRing- useWriteAudioToRingif you are writing the
            first data, or if the CD drive in use does not require
            stitching. UseStitchAudioIntoRingif the CD
            drive requires stitching, and this is not the first bit
            of data to play (in other words, there should be overlap
            from a previous read). You can call this function at
            interrupt time. 
 
 
| Note:If stitching is required by the CD drive, you
         must read overlapping data from the drive. For instance, if
         one read you get 75 blocks starting at address 01:15:50 (one
         minute, 15 seconds, 50 blocks), the next read should overlap
         by some amount. I have found that an overlap of 7 blocks
         gives good results. Thus the next read would read 75 blocks
         starting at address 01:16:43 (7 blocks shy of a full
         second). You need to pass the
 StitchAudioIntoRingthe number of frames of overlap that you're using. |  
 
 
            PlayRingandPauseRingcan
            be used to start and stop the audio at any time.PlayRingwill start the sound as soon as
            possible.PauseRingwill stop the sound from
            playing as soon as possible. These functions can be
            called at interrupt time.Call RingBytesAvailableto determine if
            you should queue another read of CD data. If there is
            enough space in the ring buffer, queue another read.
            Otherwise, stop reading. SeeReadMoreCDAudiobelow for how to get the data reads started again. This
            function can be called at interrupt time.ReadMoreCDAudiois a function that is
            called by the sound interrupt code every time an audio
            interrupt happens. The call is made at interrupt time.
            This is the way that the audio task will alert you that
            you should read more data from the CD. Because the CD
            drive will be able to read data faster than the sound
            plays it, eventually the function getting the CD audio
            will no longer have room to insert more audio data into
            the ring buffer. UsingRingBytesAvailable,
            determine the amount of available space in the ring
            buffer. If there's enough to get more data from the CD,
            and if data is not currently being read off the CD, queue
            another read.Call InvalidateRingBufferwhenever you
            are playing some user-specified different data, such as a
            mid-track switch. Call this function to instantly
            invalidate any existing audio data in the ring buffer.
            This call also removes all previously set track
            marker information. This function can be called at
            interrupt time.Call StopSoundto stop the sound output
            from happening. All sound will immediately stop. Use this
            when there's no more data to play. This function can be
            called at interrupt time.Call TeardownSoundto deallocate all
            data structures, including the ring buffer. Don't call
            any ring buffer manipulation routines after calling this
            before callingSetupSoundagain. This
            function must be called at task level, and will returncontrolErrif the current execution level is
            not task level.Call CDSoundTerminateto remove the
            sound driver if your device will no longer be offering
            digital CD audio, for instance, if your USB or FireWire
            CD drive has been disconnected. This function cannot be
            called at interrupt time and must be called at task
            time. These functions are used to control how the audio
         plays or give you feedback about where in the audio stream
         you are. 
            Use GetVolumeto get the volume for the
            CD audio stream (only). The volume is passed back as a
            long in the format0x0RRR0LLLwhereRRRis the right volume andLLLis the left volume. The value ofRRRandLLLranges from0x000to0x100. Do not call this function at
            interrupt time as it may be made interrupt unsafe at some
            point in the future.Use SetVolumeto get and set the volume
            for the CD audio stream (only). The volume is passed in
            as a long in the format0x0RRR0LLLwhereRRRis the right volume andLLLis the left volume. The value ofRRRandLLLmust be in the range of0x000to0x100. Do not call
            this function at interrupt time as it may be made
            interrupt unsafe at some point in the future.Use Set3DSoundOnto turn on 3D spatial
            enhancement. Do not call this function at interrupt time
            as it may be made interrupt unsafe at some point in the
            future.Use Set3DSoundOffto turn off 3D spatial
            enhancement. Do not call this function at interrupt time
            as it may be made interrupt unsafe at some point in the
            future. 
 
 
| Note:
 Set3DSoundOnandSet3DSoundOffwill return an error if 3D sound
         enhancement is not supported by the hardware. |  
 
 
            Use SetTrackMarkerto mark the next data
            being written to the ring. You can pass any arbitrary 4
            byte value. This value will be passed back if that data
            is currently being played when aGetCurrentTrackMarkercall is made. This
            function can be called at interrupt time.Use GetCurrentTrackMarkerto retrieve
            the marker that was last passed as audio data is being
            played. Along with the marker that was passed, a frame
            count is returned that tells how far beyond the marker
            has been played. This function can be called at interrupt
            time. There are a significant number of data structures
         and memory allocations associated with digital CD audio. To
         minimize the use of system resources that are not needed,
         your driver should not call SetupSounduntil it
         is actually going to play a CD. Likewise, it should callTeardownSoundas soon as it is done playing the
         CD so that system resources can be freed for other
         applications. Back to top 
 
 Additional Notes & CommentsThe Only WayThe only way that users will be able to hear their
         CDs through USB speakers is for the CD/DVD driver to support
         digital audio. If you are the author of a CD or DVD driver,
         you should work to add this functionality to your driver as
         quickly as possible. The Apple CD/DVD driver allows for digital CD audio
         only on Macintoshes which have ATAPI CD or DVD drives. It
         does not support SCSI CD drives. Macintoshes with SCSI CD
         drives using the Apple CD/DVD driver will behave as they
         always have. The iBook only does digital CD audio, as its
         sound chip does not have an analog to digital converter
         (remember, it doesn't have a built in microphone either).
         All iBooks will play audio CD using the above API. If a user
         installs a third-party CD driver on the iBook, it is
         imperative that it supports digital CD audio or the user
         will loose the ability to hear their audio CDs. The Power Macintosh G4 (AGP Graphics) only does
         digital CD audio as there is no internal CD audio analog
         connection on the motherboard. Though the computer does
         support analog recording via an external microphone, it does
         not have an internal analog connection. 3D SoundThe 3D sound enhancement that is offered is a
         simple filter. It is one of a class of filters called
         "stereo spreaders." This type of enhancement works well with
         some types of music, and not so well with others, so make
         sure you allow the user to choose their personal preference
         of on or off. Because of the additional signal from the stereo
         spreader is being added back into the original signal, the
         overall signal is reduced to avoid the possibility of
         clipping. This has the effect of reducing the overall volume
         level of the sound when the 3D effect is turned on (and a
         raising of the volume when it is turned off). The user can
         compensate for this by turning up the volume on the Mac, the
         CD, or their speakers. The current implementation of the 3D-Stereo
         component takes about 1.4% of the CPU on a 300MHz PowerBook
         G3. Back to top 
 
 SummaryAs you can see, applications do not have to do
         anything special and will just continue to work -- 
         assuming that they were properly coded with the correct
         error handling and user interface. If you do not have a user
         interface for sound preferences, but instead rely on the
         Sound control panel, please remedy this as soon as
         possible. Drivers have a bit more work to allow for digital
         CD audio, but the benefit of allowing the user to play their
         CDs through their USB speakers definitely makes this effort
         worthwhile. ReferencesTN1124: New Sound Input Driver
            Features TN1108: Unknown Sound Features
Back to top  
 Downloadables
 
 
 Back to top |