[haiku-3rdparty-dev] Playing a sound with BSoundPlayer from a BMediaTrack

  • From: Robert Stiehler <r.stiehler85@xxxxxxxxxxxxxx>
  • To: haiku-3rdparty-dev@xxxxxxxxxxxxx
  • Date: Sat, 25 Jun 2011 06:39:47 +0200

Hi,

actual i am trying to play a sound from a BMediaTrack. For this i found an
old example class from Be.
The BMediaTrack is stored in an BMallocIO object, so it's stored in the
memory (later more).

Here the example from Be.
############################

++++++++++++++AudioOutput.h ++++++++++++++++

#ifndef _AUDIO_OUTPUT_H
#define _AUDIO_OUTPUT_H

#include <SoundPlayer.h>
#include <OS.h>
#include "MediaTrack.h"

class AudioOutput {
public :
                    AudioOutput(BMediaTrack *track, const char *name);
                    ~AudioOutput();
    void            SetTack(BMediaTrack *new_track);
    status_t        InitCheck() { return ((player != NULL)?B_OK:B_ERROR); };
    BMediaTrack        *Track() { return track; };
    status_t        SeekToTime(bigtime_t *inout_time);
    status_t        Play();
    status_t        Stop();
    bool            IsPlaying() { return isPlaying; };
    void            WaitForAudio();
    bigtime_t        TrackTimebase();

private :
    friend void AudioPlay(void *, void *, size_t, const
media_raw_audio_format &);

    void            Lock();
    void            Unlock();

    bool            isPlaying;
    int32            frameSize;
    int32            lock_count;
    int32            channelCount;
    int8            default_data;
    uint32            frame_size;
    float            frame_rate;
    uint32            buffer_size;
    sem_id            lock_sem;
    sem_id            wait_sem;
    BMediaTrack        *track;
    BSoundPlayer    *player;
    bigtime_t        perfTime, trackTime;
};

#endif


######################

+++++++++++++AudioOutput.cpp+++++++++++++++++

#include "AudioOutput.h"
#include <stdio.h>
#include <string.h>


void
AudioPlay(void *cookie, void *buffer, size_t bufferSize, const
media_raw_audio_format &format) {
    bool            update_trackTime;
    int64            frame_count;
    uint32            filled;
    status_t        err;
    AudioOutput        *ao;
    media_header    mh;

    ao = (AudioOutput*)cookie;
    ao->Lock();

    update_trackTime = true;

    if(ao->isPlaying) {
        err = ao->track->ReadFrames((char*)buffer, &frame_count, &mh);
        if((err != B_OK) || (frame_count < 0)) {
            memset((char*)buffer, ao->default_data, ao->buffer_size);
            update_trackTime = false;
        }
        else {
            filled = ao->frame_size * frame_count;
            if(filled < ao->buffer_size) {
                memset((char*)buffer+filled, ao->default_data,
ao->buffer_size-filled);
            }
            if(err != B_OK) {
                update_trackTime = false;
            }
        }
    }
    else {
        memset((char*)buffer, ao->default_data, ao->buffer_size);
    }

    ao->perfTime = ao->player->PerformanceTime();
    if(update_trackTime) {
        ao->trackTime = ao->track->CurrentTime();
    }
    else {
        ao->trackTime += (bigtime_t)(1e6 * (float)bufferSize /
((float)ao->frame_size * ao->frame_rate));
        release_sem(ao->wait_sem);
    }

    ao->Unlock();
}


AudioOutput::AudioOutput(BMediaTrack *new_track, const char *name) {
    media_format    format;

    lock_count = 0;
    lock_sem = create_sem(0, "audio output");
    wait_sem = create_sem(1, "wait for audio");
    track = new_track;
    isPlaying = false;
    perfTime = -1;
    perfTime = -1;
    trackTime = 0;

    track->DecodedFormat(&format);
    switch(format.u.raw_audio.format) {
    case media_raw_audio_format::B_AUDIO_UCHAR :
        default_data = 0x80;
        frame_size = 1;
        break;
    case media_raw_audio_format::B_AUDIO_SHORT :
        default_data = 0;
        frame_size = 2;
        break;
    case media_raw_audio_format::B_AUDIO_INT :
        default_data = 0;
        frame_size = 4;
        break;
    case media_raw_audio_format::B_AUDIO_FLOAT :
        default_data = 0;
        frame_size = 4;
        break;
    default :
        player = NULL;
        return;
    }
    channelCount = format.u.raw_audio.channel_count;
    frame_size *= channelCount;
    buffer_size = format.u.raw_audio.buffer_size;
    frame_rate = format.u.raw_audio.frame_rate;

    player = new BSoundPlayer(&format.u.raw_audio, name, AudioPlay);
    if(player->InitCheck() != B_OK) {
        delete player;
        player = NULL;
    } else {
        player->SetCookie(this);
        player->Start();
        player->SetHasData(true);
    }
}


AudioOutput::~AudioOutput() {
    //if(player)
    player->SetHasData(false);
    player->Stop(true, true);
    delete player;
    delete_sem(lock_sem);
    delete_sem(wait_sem);
}


void
AudioOutput::SetTack(BMediaTrack *new_track) {
    media_format    format;

    lock_count = 0;
    track = new_track;
    isPlaying = false;
    perfTime = -1;
    perfTime = -1;
    trackTime = 0;

    track->DecodedFormat(&format);
    switch(format.u.raw_audio.format) {
    case media_raw_audio_format::B_AUDIO_UCHAR :
        default_data = 0x80;
        frame_size = 1;
        break;
    case media_raw_audio_format::B_AUDIO_SHORT :
        default_data = 0;
        frame_size = 2;
        break;
    case media_raw_audio_format::B_AUDIO_INT :
        default_data = 0;
        frame_size = 4;
        break;
    case media_raw_audio_format::B_AUDIO_FLOAT :
        default_data = 0;
        frame_size = 4;
        break;
    default :
        player = NULL;
        return;
    }
    channelCount = format.u.raw_audio.channel_count;
    frame_size *= channelCount;
    buffer_size = format.u.raw_audio.buffer_size;
    frame_rate = format.u.raw_audio.frame_rate;

    if(player->InitCheck() != B_OK) {
        delete player;
        player = NULL;
    } else {
        player->SetCookie(this);
        player->Start();
        player->SetHasData(true);
    }
}


void
AudioOutput::Lock() {
    if(atomic_add(&lock_count, 1) > 0) {
        acquire_sem(lock_sem);
    }
}


void
AudioOutput::Unlock() {
    if(atomic_add(&lock_count, -1) > 1) {
        release_sem(lock_sem);
    }
}


status_t
AudioOutput::SeekToTime(bigtime_t *inout_time) {
    status_t    err;

    Lock();
    err = track->SeekToTime(inout_time);
    trackTime = *inout_time;
    Unlock();
    return err;
}


status_t
AudioOutput::Play() {
    Lock();
    acquire_sem(wait_sem);
    isPlaying = true;
    Unlock();
    return B_NO_ERROR;
}


status_t
AudioOutput::Stop() {
    isPlaying = false;
    release_sem(wait_sem);
    return B_NO_ERROR;
}


void
AudioOutput::WaitForAudio() {
    if(IsPlaying()) {
        acquire_sem(wait_sem);
    }
}


bigtime_t
AudioOutput::TrackTimebase() {
    return perfTime - trackTime;
}

####################################


To play the sound in the BMallocIO object (CAudioStream_model inherits from
BMallocIO) i put it into a BMediaFile and extract there the BMediaTrack.
All this works well.

####################################

void
CAudio_controller::PlaySound(CAudioStream_model &audioStreamModel, char*
name) {
    audioStreamModel.Seek(0, SEEK_SET);
    BMediaFile *audioDestination = new BMediaFile(&audioStreamModel);

    if(audioDestination->InitCheck() != B_OK) {
        return;
    }

    BMediaTrack *track = audioDestination->TrackAt(0);

    if(track == NULL) {
        printf("No track!!!");
        return;
    }

    audioOut = new AudioOutput(track, name);


    if(audioOut->InitCheck() != B_OK) {
        return;
    }
    if(audioOut->Play() != B_OK) {
        return;
    }

    audioOut->WaitForAudio();
    audioOut->Stop();
    delete audioOut;
    delete audioDestination;
}

###################################

Now to the Problem:

It works all well, so far i just call the PlaySound method just with audio
stuff with the same encoding. If i call it for a sound in raw and the in
vorbis it crashs, when i just call it with for vorbis encoded it works and
if i just call it with raw it works.
Or as an example (fRecFile is from BMallocIO and contains audio in wave,
fCompresedAudioStream is from BMallocIO and contains audio in vorbis)

// That works (play sound once)
    PlaySound(*fRecFile, "audio playback");
// That works end

// That works (play sound twice)
    PlaySound(*fRecFile, "audio playback");
    PlaySound(*fRecFile, "audio playback");
// That works end

//That works to (play sound once)
PlaySound(*fCompresedAudioStream, "audio playback 2");
//That works to end
 //That works to (play sound twice)
PlaySound(*fCompresedAudioStream, "audio playback 2");
PlaySound(*fCompresedAudioStream, "audio playback 2");
//That works to end
 //That works not (play sound twice in diffrent encodings)
    PlaySound(*fRecFile, "audio playback");
    PlaySound(*fCompresedAudioStream, "audio playback 2");
    //That works not end
When i call it for to diffrent audio types it crashes in the
"AudioPlay(void *cookie, void *buffer, size_t bufferSize, const
media_raw_audio_format &format)"
function.
While "err = ao->track->ReadFrames((char*)buffer, &frame_count, &mh);"

Can someone help me and say me where the problem is?

best regards,
Robert

Other related posts: