bool AudioCDBurner::addAudioTrack (AudioSource* audioSource, int numSamples)
{
    if (audioSource == 0)
        return false;

    ScopedPointer<AudioSource> source (audioSource);

    long bytesPerBlock;
    HRESULT hr = pimpl->redbook->GetAudioBlockSize (&bytesPerBlock);

    const int samplesPerBlock = bytesPerBlock / 4;
    bool ok = true;

    hr = pimpl->redbook->CreateAudioTrack ((long) numSamples / (bytesPerBlock * 4));

    HeapBlock <byte> buffer (bytesPerBlock);
    AudioSampleBuffer sourceBuffer (2, samplesPerBlock);
    int samplesDone = 0;

    source->prepareToPlay (samplesPerBlock, 44100.0);

    while (ok)
    {
        {
            AudioSourceChannelInfo info;
            info.buffer = &sourceBuffer;
            info.numSamples = samplesPerBlock;
            info.startSample = 0;
            sourceBuffer.clear();

            source->getNextAudioBlock (info);
        }

        buffer.clear (bytesPerBlock);

        typedef AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian,
                AudioData::Interleaved, AudioData::NonConst> CDSampleFormat;

        typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian,
                AudioData::NonInterleaved, AudioData::Const> SourceSampleFormat;

        CDSampleFormat left (buffer, 2);
        left.convertSamples (SourceSampleFormat (sourceBuffer.getSampleData (0)), samplesPerBlock);
        CDSampleFormat right (buffer + 2, 2);
        right.convertSamples (SourceSampleFormat (sourceBuffer.getSampleData (1)), samplesPerBlock);

        hr = pimpl->redbook->AddAudioTrackBlocks (buffer, bytesPerBlock);

        if (FAILED (hr))
            ok = false;

        samplesDone += samplesPerBlock;

        if (samplesDone >= numSamples)
            break;
    }

    hr = pimpl->redbook->CloseAudioTrack();
    return ok && hr == S_OK;
}