sdlmixer.cpp

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. Createmixer
  2. sdlaudio_callback
  3. open
  4. Mix
  5. Sync
  6. close

#include "sdlmixer.h"

// -- factory method

mymixer* mymixer_factory::Createmixer()
/* [<][>][^][v][top][bottom][index][help] */
{
  return new sdlmixer();
}

void sdlaudio_callback(void* m, Uint8* stream, int len)
/* [<][>][^][v][top][bottom][index][help] */
{
  sdlmixer* me = reinterpret_cast<sdlmixer*>(m);
  if(me->bufsize != len){
    fprintf(stderr, "warning: buffer size for callback differs.(%d)\n", len);
    delete[] me->buf;
    me->bufsize = len;
    me->buf = new Uint8[len];
  }

  int mlen;
  mlen = me->ring.Get(me->buf, len);
  if(mlen == 0) return;
  SDL_MixAudio(stream, me->buf, mlen, SDL_MIX_MAXVOLUME);
}

int sdlmixer::open(int rate = 44100)
/* [<][>][^][v][top][bottom][index][help] */
{
  if(SDL_Init(SDL_INIT_AUDIO) < 0) return -1;
  fmt.freq = rate;
  fmt.format = AUDIO_S16;
  fmt.channels = 2;
  fmt.samples = 512;
  fmt.callback = sdlaudio_callback;
  fmt.userdata = this;

  bufsize = fmt.samples * 32;
  buf = new Uint8[bufsize];

  if(SDL_OpenAudio(&fmt, NULL) < 0) return -1;

  ring.bufInit(rate * 2 * 2 * 2); // 16bit 2ch 1sec
  SDL_PauseAudio(1);
}

void sdlmixer::Mix(short* _buf, int samples)
/* [<][>][^][v][top][bottom][index][help] */
{
  int remain = samples * sizeof(short);
  int ret;
  int ofs;
  Uint8* ptr = reinterpret_cast<Uint8*>(_buf);

  if(SDL_GetAudioStatus() != SDL_AUDIO_PLAYING){
    if(ring.Capacity() > 30) SDL_PauseAudio(0);
  }
  ofs = 0;
  while(1){
    if(ring.Capacity() > 50) SDL_Delay(10);
    SDL_LockAudio();
    ret = ring.Put(ptr + ofs, remain);
    SDL_UnlockAudio();

    remain -= ret;
    if(remain == 0) break;
    ofs += ret;
  }
}

void sdlmixer::Sync()
/* [<][>][^][v][top][bottom][index][help] */
{
  fprintf(stderr, "Wait for ring buffer empty.\n");
  while(!ring.isEmpty()) SDL_Delay(100);
}
void sdlmixer::close()
/* [<][>][^][v][top][bottom][index][help] */
{
  SDL_CloseAudio();
}


/* [<][>][^][v][top][bottom][index][help] */