0
0

I am in the process of building a mp3 player just for the fun of it and decided to use the FMOD API. I have gota basic player class going but I am trying to implement stop and play functions ( for example you stop the track in the middle but then press play and have it start playing from the begining of the mp3).
Anyway I am having a little trouble with understanding how the FSOUND_STOP(), FSOUND_Stream_Play() and FSOUND_Stream_PlayEx() functions work. As far as I understand if I call FSUOND_Stop() it stops the stream but the stream pointer is still valid so if I pass it to either of the FSOUND_Stream play functions it should start the stream again from the beinging, assuming I pass the right parameters. However, this is not the case when I call the Play() with the still unclosed stream pointer I get nothing playing until I call the Play() again. The funny thing that seams to happen after the second Play() call is the channel number changes and since that channel seems to be paused the un pause call un pauses it and I get sound. This behavior seems strange since on the first call I dont get the channel change. I am posting the code responsible for playing the music so you guys can help me out if you have time.

——————————-start————————————————–
int MP3Player::Play() {

int key = 0;
int channel = -1;
char filename[256];

cout << "Enter Filename: ";
cin.getline(filename, 256, '\n');

stream = FSOUND_Stream_Open(&filename[0], FSOUND_NORMAL | FSOUND_MPEGACCURATE, 0, 0);

if (!stream)
{
    printf("Error!\n");
    printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
    FSOUND_Close();

    return 1;
}
// ==========================================================================================
// SET AN END OF STREAM CALLBACK AND RIFF SYNCH POINTS CALLBACK
// ==========================================================================================
FSOUND_Stream_SetEndCallback(stream, endcallback, 0);
FSOUND_Stream_SetSyncCallback(stream, endcallback, 0);


printf("=========================================================================\n");
printf("Press SPACE to pause/unpause\n");
printf("Press 'f'   to fast forward 2 seconds\n");
printf("Press 's' to stop playing the music\n");
printf("Press 'p' to play music\n");
printf("Press ESC   to quit\n");
printf("=========================================================================\n");
printf("Playing stream...\n\n");

sptr = FSOUND_Stream_GetSample(stream);
if (sptr)
{
    int freq;
    FSOUND_Sample_GetDefaults(sptr, &freq, NULL, NULL, NULL);
    printf("Name      : %s\n", FSOUND_Sample_GetName(sptr));
    printf("Frequency : %d\n\n", freq);
}

do
{
    if (channel < 0)
    {
        // ==========================================================================================
        // PLAY STREAM
        // ==========================================================================================
        channel = FSOUND_Stream_PlayEx(FSOUND_FREE, stream, NULL, TRUE);
        FSOUND_SetPaused(channel, FALSE);
        isPlaying = true;
    }

    if (kbhit())
    {
        key = getch();
        if (key == ' ')
        {
            Pause(channel);
        }
        else if (key == 'f')
        {
            FastForward(1000);
        }
        else if (key == 's')
        {
            Stop();
        }
        else if (key = 'p')
        {
            int test = FSOUND_IsPlaying(channel);
            channel = FSOUND_Stream_PlayEx(channel, stream, NULL, FALSE);
            test = FSOUND_IsPlaying(channel);

            FSOUND_SetPaused(channel, FALSE);
        }
    }

    Display();

    Sleep(10);

}while (key != 27 && isPlaying);        //check

return 0;

}

void MP3Player::Display() {

printf("pos %6d/%6d time %02d:%02d/%02d:%02d cpu %5.02f%%   \r", FSOUND_Stream_GetPosition(stream), 
                                                                     FSOUND_Stream_GetLength(stream), 
                                                                     FSOUND_Stream_GetTime(stream) / 1000 / 60, 
                                                                     FSOUND_Stream_GetTime(stream) / 1000 % 60, 
                                                                     FSOUND_Stream_GetLengthMs(stream) / 1000 / 60, 
                                                                     FSOUND_Stream_GetLengthMs(stream) / 1000 % 60, 
                                                                     FSOUND_GetCPUUsage());

}

void MP3Player::Pause(int channel) {

FSOUND_SetPaused(channel, !FSOUND_GetPaused(channel));

}

void MP3Player::FastForward(int time) {

FSOUND_Stream_SetTime(stream, FSOUND_Stream_GetTime(stream) + time);

}

void MP3Player::Stop() {

FSOUND_Stream_Stop(stream);

}
——————————————end—————————————-

As most will notice some of the code is from the example. I am from the school of thought if it aint broke dont fix it 😆 .

p.s. Thanks for any help you can give. also if you see variables without definitions just so you know they are declared in the H file properly. still if you need to know what they are defined as and how just reply and Iwill place the extra info.

  • You must to post comments
0
0

Hey brett thanks for the quick response that totally solved my problem. I have another question though. First off since the tip you gave me has me cycling through free channels to play the stream on I have to ask does the API automatically free up unused channels? Lastly, I would like to make the call back function a part of the player class either a private member or public (not sure if the class restrictions still hold for function pointers). however when I try to pass a public function member of the player class as a callback function I get the following error:

——————————-Error Begin——————————————

error C2664: ‘FSOUND_Stream_SetEndCallback’ : cannot convert parameter 2 from ‘signed char (struct FSOUND_STREAM *,void *,int,void *)’ to ‘signed char (__stdcall *)(struct FSOUND_STREAM *,void *,int
,void *)’
None of the functions with this name in scope match the target type

——————————–Error End——————————————-

I have no idea how to do this and I figure the callback fucntion will allow me the ability to set certain flags that I will need if I have a play list in the player and need to advance to the next track.

p.s. Thanks for your time.

  • You must to post comments
0
0

Hey brett thanks for your help. I had already tried adding the (__stdcall *) to the function signature in both the implementation file nad the header file. I would try it before the F_CALLBACKAPI and after however I still was getting an error. your answer jarred a solution free in my head though, not sure if this is what you meant.

I recently picked up a website by the name of [url:2xfxdgc8]http://www.function-pointer.org[/url:2xfxdgc8]. it explained the problem I had ran into and a solution to the problem….

“Pointers to non-static members are different to ordinary C function pointers since they need the this-pointer of a class object to be passed. Thus ordinary function pointers and non-static member functions have different and incompatible signatures! If you just want to callback to a member of a specific class you just change your code from an ordinary function pointer to a pointer to a member function. But what can you do, if you want to callback to a non-static member of an arbitrary class? It’s a little bit difficult. You need to write a static member function as a wrapper. A static member function has the same signature as a C function! Then you cast the pointer to the object on which you want to invoke the member function to void* and pass it to the wrapper as an additional argument or via a global variable. If you use a global variable it is very important, that you make sure that it will always point to the correct object! Of course you’ve also got to pass the calling arguments for the member function. The wrapper casts the void-pointer to a pointer to an instance of the corresponding class and calls the member function.”

I opted to use the first option since I am not fond of global variables unless I am either too lazy or need a quick fix to an annoying problem. Once again I am not sure if this is what you meant for me to do but if it wasnt then anyone else trying to do the same thing I was will have a possible additional solution to the problem.

  • You must to post comments
0
0

When a stream is created I get a pointer to that stream to use in my code to play the music. However, I am at the stage of implementing playlist capabilities into the player and I want to know if I need to explicitly call the delete on the stream pointer when I move to another track or does the library automatically take care of that allowing me to simple change the address the stream pointer is pointing top.

One more thing. I am basically using the tactic of beginning a bran new stream as I go through each song on the list. This is forcing me to have to call FSOUND_INIT() everytime I start a new song and set the call backs everytime I get to a new song. is there anyway I can avcid this?

Thanks for your help

  • You must to post comments
0
0

Initially I had it setup so that when the player object gets created, fmod is initialized. However, I would get an error everytime I tried to play another song after the first song finished. So if I had a 2 song playlist the first song would play fine but then at the end of the first song I would get an error saying that I cant call FSOUND_Stream_Open() without calling FSOUND_Init() first. Basically, the code responsible for handling changing the songs would simple change a flag in the player object signalling that the song has ended ( this would be done in the endcallback() ) and supply the FSOUND_Stream_Play() with the filename of the next song to play. I could only get past the error by having FMOD initialized (by calling FSOUND_Init()) just before my call to FSOUND_Stream_Open().

  • You must to post comments
Showing 4 results
Your Answer

Please first to submit.