PrimoBurner

How to create a hidden track at the beginning of a CD – Part 2

PrimoBurnerSDK 3.5.6 introduced a new way for writing hidden tracks to audio CDs.

Before 3.5.6 there would always be a digital silence of 2 seconds at the start of the pre-gap on the first track.

Now PrimoBurner allows the first two seconds to be filled with audio too. All that needs to be done is to set the pre-gap start of the first track to -150. The following code shows how you can use the new feature:

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 pre-gap start value other than -150 and less then 0 will result in AUDIOCD_INVALID_CD_SESSION error.

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.

There is a new IAudioInput::SetForceMinTrackLength method that controls that behavior. If you have to create a track from small audio segments call SetForceMinTrackLength(FALSE) to disable the track length validation.