by Yavor N.
14. November 2010 14:00
PrimoBurnerSDK v3.5.6 introduced a new way for writing hidden tracks in audio CDs. Until now there would always be a digital silence of 2 seconds at the start of the pregap on the first track. Now PrimoBurner SDK allows these two seconds to be filled with user data as well. To achieve this all that needs to be done is set the pregap start of the first track to -150. The following code demonstrates this new behavior:
void WriteToCD_HiddenTrack_With_User_Data_In_First_2seconds(char driveLetter)
{
IEngine * engine = Library::CreateEngine();
engine->Initialize();
int deviceIndex = Library::GetCDROMIndexFromLetter(driveLetter);
IDeviceEnum * devices = engine->GetDevices();
IDevice* dev = devices->GetItem(deviceIndex, 1);
IAudioCD* audio = Library::CreateAudioCD();
audio->SetDevice(dev);
audio->SetAudioDecodingMethod(ADM_MEMORY);
char_t* inputPath = _T("C:\\sample.wav");
IAudioInput* ain = Library::CreateAudioInput();
ain->SetFilePath(inputPath);
bool_t res = audio->GetAudioInputsRef()->Add(ain);
if (!res)
{
// failed to add audio input
return;
}
// Leave AudioCD to be the single owner the IAudioInput instance
ain->Release();
ain = NULL;
int32_t len1 = audio->GetInputLength(audio->GetAudioInputsRef()->GetItemRef(0));
// It is essential that the audio input should be 2 seconds longer than usual,
// since the first 150 frames(blocks) of the input will be written in the 2s pregap
// that is usually filled with digital silence
printf("audio frames: %d", len1);
ICDSession* pSession = Library::CreateCDSession();
pSession->SetType(ST_CDDA);
ICDTrack* pTrack = Library::CreateCDTrack();
pTrack->SetType(TT_AUDIO);
// CD_PREGAP_START equals -150 - this will allow you to write user data in
// the first 2 seconds of the pregap as well
pTrack->SetPregapStart(CD_PREGAP_START);
// Just leave the first 2 seconds as the intended pregap (hidden track) and continue
// from address 0 with the rest of the audio input data
pTrack->SetStart(0);
int32_t pos = len1 - 1;
// Since the first two seconds of the audio input will be in the pregap,
// then the actual end is CD_PREGAP_LENGTH blocks earlier as well.
pTrack->SetEnd(pos - CD_PREGAP_LENGTH);
// The same goes for the postgap
pTrack->SetPostgapEnd(pos - CD_PREGAP_LENGTH);
pSession->GetTracksRef()->Add(pTrack);
pTrack->Release();
audio->SetCDSession(pSession);
pSession->Release();
res = audio->WriteToCD();
if (!res)
{
printf("\n last error: 0x%x \n ", audio->GetLastError());
}
audio->Release();
dev->Release();
devices->Release();
engine->Shutdown();
engine->Release();
}
Note the CD_PREGAP_START constant – it is a negative value and equals -150. Using a pregap start value other than -150 and less then 0 will result in AUDIOCD_INVALID_CD_SESSION error.
Also, there is a new method added to IAudioInput interface called SetForceMinTrackLength – if you intend to form a single audio track from several small audio inputs then it may be better to call this method with FALSE as input parameter for each of these inputs. By default PrimoBurner SDK ensures that the audio inputs could provide at least 4 seconds of data – any inputs that are shorter will have trailing silence added when burned to the disc. The new method allows one to override this behavior. There is also a corresponding ‘get’ method in IAudioInput interface called GetForceMinTrackLength.