Writing Audio CDs
Burn Audio CDs using IMAPI on XP and above
"Perhaps they were expecting someone to write an audio recorder in Visual Basic?" Paul DiLascia writes, somewhat sarcastically, in the April 2004 issue of MSDN Magazine on the subject of the Image Mastering API. Whether they were expecting it or not, here it is: a VB application which creates audio CDs.
Writing Audio CDs
In the article on IMAPI I demonstrated a wrapper and a simple properties sample showing how to use the CD Image Mastering API provided on XP and above. As noted, the API provides two mastering interfaces for building a CD image; IRedbookDiscMaster for creating audio CDs and IJolietDiscMaster for creating data CDs. This articleshows how to use the audio CD interface.
Assuming you have completed the initial task of picking which songs you want to include on the CD, there are four main steps in creating an audio CD using IMAPI:
I'll cover doing these in turn.
1. Selecting a Disc Recorder
In order to select a recorder, you must first have a cDiscMaster instance. Once you have that, then get a RedbookDiscMaster instance, which sets the disc mastering format to audio. You can then select the recorder to use using the Recorders collection:
Private m_cDiscMaster As cDiscMaster Private m_cRedbook As cRedbookDiscMaster Dim cRecorder As cDiscRecorder ' Get an instance of the DiscMaster object: Set m_cDiscMaster = New cDiscMaster m_cDiscMaster.Initialise ' Set the active mastering format to Redbook ' and obtain a Redbook Mastering instance: Set m_cRedbook = m_cDiscMaster.RedbookDiscMaster ' Set the active recorder (nIndex is the 1-based index ' of the recorder you want): m_cDiscMaster.Recorders(nIndex).SetAsActive Set cRecorder = m_cDiscMaster.Recorders.ActiveRecorder ' .. other steps to complete the CD ' Clear up Set cRecoder = Nothing Set m_cRedbook = nothing m_cDiscMaster.ClearUp
Note that any image you stage using cRedbookDiscMaster will be freed if you request the RedbookDiscMaster object again, or if you change the disc mastering format through the JolietDiscMaster method. You should therefore keep a reference to the object until the burn has completed. The image is also freed whenever the cDiscMaster object is released.
2. Checking the Recorder Media
To determine what media is available in the recorder, use the MediaInfo method of the cDiscRecorder object. Note that to get information about the media you must first open the recorder for exclusive access; make sure you close it again otherwise you will get an error when you try to burn the disc:
' Exclusively open the recorder: cRecorder.OpenExclusive ' Get the media info: Set cInfo = cRecorder.MediaInfo ' We can close the recorder now: cRecorder.CloseExclusive ' Check we have media and that it is writable: If (cInfo.MediaPresent) And _ ((cInfo.mediaflags And MEDIA_WRITABLE) = MEDIA_WRITABLE) Then ' ... Staging and burning End If
3. Building up the CD Image
In order to build up the CD image, you need to have a way of getting chunks of wave data which can be accessed through a memory pointer. In this sample, I've used the cWaveReader class which was introduced in the Wav File Viewer Control. However, any other source of data can be used, provided the data is arranged as a 16-bit stereo 44.1kHz wave file.
The image is staged by adding tracks using the CreateTrack method. This takes the number of blocks for the track as a parameter, although the documentation suggests this is optional. Once the track is open, data is added using the AddAudioTrackBlocks method. Data must be added in chunks of the audio block size, so if the audio is not an even multiple of 2352 bytes (1/75 second) then padding zeros are needed. Finally, once all the data has been added for a track then class CloseTrack. Here's the code for creating one track:
Private Sub addTrack(ByVal sFile As String) Dim lBlockSize As Long Dim cWav As cWavReader Dim lTrackSize As Long Dim lTrackBlocks As Long Dim bMore As Boolean ' Get block size: lBlockSize = m_cRedbook.AudioBlockSize ' Create a WAVE reader and set the buffer size ' to the block size: Set cWav = New cWavReader cWav.ReadBufferSize = lBlockSize \ 4 cWav.OpenFile sFile ' Evaluate the number of blocks in the track: lTrackSize = cWav.AudioLength * 4 lTrackBlocks = lTrackSize \ lBlockSize If (lTrackSize Mod lBlockSize) > 0 Then lTrackBlocks = lTrackBlocks + 1 End If ' Create the audio track: m_cRedbook.CreateAudioTrack lTrackBlocks ' Add audio data until there is none left: Do bMore = cWav.Read If (bMore) Then lReadSize = cWav.ReadSize * 4 cWav.ZeroUnusedBufferBytes m_cRedbook.AddAudioTrackBlocks cWav.ReadBufferPtr, lBlockSize DoEvents End If Loop While (bMore) ' Close the track m_cRedbook.CloseAudioTrack ' Close the wave file: cWav.CloseFile End Sub
Whilst adding tracks, you need to determine whether there is enough space on the CD to fit the selected tracks. There are two ways of doing this: you can either precalculate whether the tracks will fit compared to the number of FreeBlocks on the disc (as I have done in this example), or you can stage the image and respond to AddProgress events from the cDiscMaster object, which will notify you of the number of blocks used and blocks available.
Note that a CD must have at least one track and no more than 99 tracks per audio CD; this is part of the Redbook specification. As far as I can tell you cannot set up trick tracks with negative offsets from the start of the CD using this API.
4. Buring the CD
To burn the CD, call the RecordDisc method. This takes two boolean parameters; the first is whether to simulate the record or actually record and the second is whether to eject once recording is complete.
m_cDiscMaster.RecordDisc False, True
The method does not return until the burn has complete and once recording is underway, these events will be fired:
There are two issues with this implementation currently; any suggestions for fixing either would be a great help:
The sample recorder provided here is intentionally minimal, just being there to demonstrate that you can create an audio CD with this technique. There's quite a few things you could do to improve it:
This sample demonstrates how to create audio CDs using the IMAPI library. There are a couple of issues with the current sample but hopefully they will be resolved soon.