Sign in to follow this  

SDL_Mixer playback problem (C++)

This topic is 3465 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Got a problem with sample playback in SDL_Mixer. If I want to restart the sample (Mix_Chunk) I'm currently playing, first I have to stop it in a DIFFERENT cycle. If I stop it right before playing it, the program will crash... (OS: OSX 1.5.2; SDL_Mixer version is 1.2.8) code:
const int PAN_LEFT(0);
const int PAN_RIGHT(254);
const int PAN_CENTER(127);

struct SampleState
{
  Mix_Chunk *pChunk_;
  int channel_;
  int volume_;
  int panning_;

  explicit SampleState(Mix_Chunk *p): pChunk_(p), channel_(-1), volume_(MIX_MAX_VOLUME), panning_(PAN_CENTER) {}
  ~SampleState() {};

  bool SetSample(Mix_Chunk *pC) {
    Stop(); // SampleState doesn't own the chunk, it is only responsible for the channel
    if(pC == 0) { return false; }
    pChunk_ = pC;
    return true;
  }

  void SetVolume(int vol) {
    volume_ = vol;
    if(channel_ < 0) { return; }
    volume_ = ::Mix_Volume(channel_, volume_);
  }

  void SetPanning(int panning) {
    panning_ = panning;
    if(channel_ < 0) { return; }
    ::Mix_SetPanning(channel_, PAN_RIGHT - panning_, panning);
  }

  void Play(int loops = 0, int ticks = -1, int channelPref = -1) {
    if(channel_ < 0) {
      channel_ = ::Mix_PlayChannelTimed(channelPref, pChunk_, loops, ticks);
      SetVolume(volume_);
      SetPanning(panning_);
    }
  }

  void Stop() {
    if(channel_ < 0) { return; }
    ::Mix_HaltChannel(channel_);
    channel_ = -1;
  }
};

// initial setup, skipped

Mix_Chunk *pMyChunk(::Mix_LoadWAV("test.wav"));
SampleState myState(pMyChunk);

SDL_Event e;
bool done(false);
bool toProcess;

while(!done) {
  toProcess = ::SDL_PollEvent(&e);
  Uint8 *kStates(::SDL_GetKeyState(0));

  if(toProcess) {
    switch(e.type) {
    case SDL_QUIT:
      done = true;
      break;
    }
  }
  
  if(kStates[SDLK_SPACE] == 1) {
      /* crash code (if placed here):
      //myState.Stop();
      */
      myState.Play();
  }
  // non-crash code:
  else {
    myState.Stop();
  }
}


So: - when I place something that calls ::Mix_HaltChannel() in front of ::Mix_PlayChannel(), it will crash the program. - if I place it so as the two doesn't get executed in the same cycle, they're OK (I guess it's sort of a timing issue, but not being multithread(head)ed, I can't afford waiting in the performance-intensive part of the program for a comfortability feature (I used to call Stop() from within Play()). - and I can't Play() the sample again if I don't Stop(), as the channel won't be reset. I know I could do this by using a call-back function (with ::Mix_ChannelFinished), but I have no way to correspond the call-back function's signature (void (*cbfunc)(int /*channelID*/)) to my SampleStates. (attempts included storing channels in my Mixer class (basically an initializer for the SDL_Mixer) and giving SampleState a static member std::vector <SampleState*> for each channel) - if I remove the channel check in Play() I lose track of the channel and soon run out of channels -> crash. do I have a completely wrong grasp on SDL_Mixer with this SampleState model? does it make sense at all to write a C++ 'wrapper' around SDL_Mixer? [Edited by - trajectorymodifier on June 23, 2008 8:00:40 AM]

Share this post


Link to post
Share on other sites
You must check the result of SDL_PollEvent and only handle the event if it actually exists! Fix that and see if it makes a difference. It probably won't, but it's worth eliminating.

(And PAN_RIGHT should probably be 255, no?)

Share this post


Link to post
Share on other sites
thanks Kylotan, fixed it. I guess I should've put the SDL_GetKeyState() version the first place, as it's not only truer to what's in the original code, but clearer too... (in the original I only used e (after polling) to check against an SDL_QUIT)

unfortunately, it wasn't the problem.

Share this post


Link to post
Share on other sites

This topic is 3465 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this