Exemple #1
0
gau_SampleSourceLoop* gau_sample_source_create_loop(ga_SampleSource* in_sampleSrc)
{
  gau_SampleSourceLoop* ret = gcX_ops->allocFunc(sizeof(gau_SampleSourceLoop));
  gau_SampleSourceLoopContext* ctx = &ret->context;
  gc_int32 sampleSize;
  ga_sample_source_init(&ret->sampleSrc);
  ga_sample_source_acquire(in_sampleSrc);
  ga_sample_source_format(in_sampleSrc, &ret->sampleSrc.format);
  sampleSize = ga_format_sampleSize(&ret->sampleSrc.format);
  ctx->triggerSample = -1;
  ctx->targetSample = -1;
  ctx->loopCount = 0;
  ctx->loopMutex = gc_mutex_create();
  ctx->innerSrc = in_sampleSrc;
  ctx->sampleSize = sampleSize;
  ret->sampleSrc.flags = ga_sample_source_flags(in_sampleSrc);
  ret->sampleSrc.flags |= GA_FLAG_THREADSAFE;
  assert(ret->sampleSrc.flags & GA_FLAG_SEEKABLE);
  ret->sampleSrc.readFunc = &gauX_sample_source_loop_read;
  ret->sampleSrc.endFunc = &gauX_sample_source_loop_end;
  ret->sampleSrc.readyFunc = &gauX_sample_source_loop_ready;
  ret->sampleSrc.seekFunc = &gauX_sample_source_loop_seek;
  ret->sampleSrc.tellFunc = &gauX_sample_source_loop_tell;
  ret->sampleSrc.closeFunc = &gauX_sample_source_loop_close;
  return ret;
}
Exemple #2
0
ga_SampleSource* gau_sample_source_create_stream(ga_StreamManager* in_mgr, ga_SampleSource* in_sampleSrc, gc_int32 in_bufferSamples)
{
  gau_SampleSourceStream* ret = gcX_ops->allocFunc(sizeof(gau_SampleSourceStream));
  gau_SampleSourceStreamContext* ctx = &ret->context;
  gc_int32 sampleSize;
  ga_BufferedStream* stream;
  ga_sample_source_init(&ret->sampleSrc);
  ga_sample_source_format(in_sampleSrc, &ret->sampleSrc.format);
  sampleSize = ga_format_sampleSize(&ret->sampleSrc.format);
  stream = ga_stream_create(in_mgr, in_sampleSrc, in_bufferSamples * sampleSize);
  if(stream)
  {
    ctx->stream = stream;
    ret->sampleSrc.flags = ga_stream_flags(stream);
    ret->sampleSrc.flags |= GA_FLAG_THREADSAFE;
    ret->sampleSrc.readFunc = &gauX_sample_source_stream_read;
    ret->sampleSrc.endFunc = &gauX_sample_source_stream_end;
    ret->sampleSrc.readyFunc = &gauX_sample_source_stream_ready;
    if(ret->sampleSrc.flags & GA_FLAG_SEEKABLE)
    {
      ret->sampleSrc.seekFunc = &gauX_sample_source_stream_seek;
      ret->sampleSrc.tellFunc = &gauX_sample_source_stream_tell;
    }
    ret->sampleSrc.closeFunc = &gauX_sample_source_stream_close;
  }
  else
  {
    gcX_ops->freeFunc(ret);
    ret = 0;
  }
  return (ga_SampleSource*)ret;
}
Exemple #3
0
gc_int32 gaX_read_samples_into_stream(ga_BufferedStream* in_stream,
                                      gc_CircBuffer* in_buffer,
                                      gc_int32 in_samples,
                                      ga_SampleSource* in_sampleSrc)
{
  void* dataA;
  void* dataB;
  gc_uint32 sizeA = 0;
  gc_uint32 sizeB = 0;
  gc_int32 numBuffers;
  gc_int32 numWritten = 0;
  ga_Format fmt;
  gc_int32 sampleSize;
  gc_CircBuffer* b = in_buffer;
  ga_sample_source_format(in_sampleSrc, &fmt);
  sampleSize = ga_format_sampleSize(&fmt);
  numBuffers = gc_buffer_getFree(b, in_samples * sampleSize, &dataA, &sizeA, &dataB, &sizeB);
  if(numBuffers >= 1)
  {
    numWritten = ga_sample_source_read(in_sampleSrc, dataA, sizeA / sampleSize, &gaX_stream_onSeek, in_stream);
    if(numBuffers == 2 && numWritten == sizeA)
      numWritten += ga_sample_source_read(in_sampleSrc, dataB, sizeB / sampleSize, &gaX_stream_onSeek, in_stream);
  }
  gc_buffer_produce(b, numWritten * sampleSize);
  return numWritten;
}
Exemple #4
0
gc_result gaX_device_queue_openAl(ga_DeviceImpl_OpenAl* in_device,
                                  void* in_buffer)
{
  gc_int32 formatOal;
  gc_int32 sampleSize;
  ALint state;
  gc_int32 bps = in_device->format.bitsPerSample;
  ga_DeviceImpl_OpenAl* d = in_device;

  if(in_device->format.numChannels == 1)
    formatOal = (gc_int32)(bps == 16 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8);
  else
    formatOal = (gc_int32)(bps == 16 ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO8);
  sampleSize = ga_format_sampleSize(&in_device->format);
  alBufferData(d->hwBuffers[d->nextBuffer], formatOal, in_buffer,
               (ALsizei)in_device->numSamples * sampleSize, in_device->format.sampleRate);
  CHECK_AL_ERROR;
  if(AUDIO_ERROR != AL_NO_ERROR)
    return GC_ERROR_GENERIC;
  alSourceQueueBuffers(d->hwSource, 1, &d->hwBuffers[d->nextBuffer]);
  CHECK_AL_ERROR;
  if(AUDIO_ERROR != AL_NO_ERROR)
    return GC_ERROR_GENERIC;
  d->nextBuffer = (d->nextBuffer + 1) % d->numBuffers;
  --d->emptyBuffers;
  alGetSourcei(d->hwSource, AL_SOURCE_STATE, &state);
  CHECK_AL_ERROR;
  if(state != AL_PLAYING)
  {
    /* NOTE: calling this, even as a 'noop', can cause a clicking sound. */
    alSourcePlay(d->hwSource);
  }
  CHECK_AL_ERROR;
  return GC_SUCCESS;
}
Exemple #5
0
Fichier : ga.c Projet : Botyto/Core
ga_Sound* ga_sound_create_sample_source(ga_SampleSource* in_sampleSrc)
{
  ga_Sound* ret = 0;
  ga_Format format;
  gc_int32 dataSize;
  gc_int32 totalSamples;
  ga_SampleSource* sampleSrc = in_sampleSrc;
  gc_int32 sampleSize;
  ga_sample_source_format(sampleSrc, &format);
  sampleSize = ga_format_sampleSize(&format);
  ga_sample_source_tell(sampleSrc, &totalSamples);
  if(totalSamples > 0)
  {
    /* Known total samples*/
    char* data;
    ga_Memory* memory;
    dataSize = sampleSize * totalSamples;
    data = gcX_ops->allocFunc(dataSize);
    ga_sample_source_read(sampleSrc, data, totalSamples, 0, 0);
    memory = gaX_memory_create(data, dataSize, 0);
    if(memory)
    {
      ret = ga_sound_create(memory, &format);
      if(!ret)
        ga_memory_release(memory);
    }
    else
      gcX_ops->freeFunc(data);
  }
  else
  {
    /* Unknown total samples */
    gc_int32 BUFFER_SAMPLES = format.sampleRate * 2;
    char* data = 0;
    ga_Memory* memory;
    totalSamples = 0;
    while(!ga_sample_source_end(sampleSrc))
    {
      gc_int32 numSamplesRead;
      data = gcX_ops->reallocFunc(data, (totalSamples + BUFFER_SAMPLES) * sampleSize);
      numSamplesRead = ga_sample_source_read(sampleSrc, data + (totalSamples * sampleSize), BUFFER_SAMPLES, 0, 0);
      if(numSamplesRead < BUFFER_SAMPLES)
      {
        data = gcX_ops->reallocFunc(data, (totalSamples + numSamplesRead) * sampleSize);
      }
      totalSamples += numSamplesRead;
    }
    memory = gaX_memory_create(data, totalSamples * sampleSize, 0);
    if(memory)
    {
      ret = ga_sound_create(memory, &format);
      if(!ret)
        ga_memory_release(memory);
    }
    else
      gcX_ops->freeFunc(data);
  }
  return ret;
}
Exemple #6
0
int main(int argc, char** argv)
{
  ga_Format fmt;
  ga_Device* dev;
  gc_int16* buf;
  gc_int32 numSamples;
  gc_int32 sampleSize;
  gc_int32 numToQueue;
  gc_int32 i;
  gc_int16 sample;
  gc_float32 pan = 1.0f;
  gc_float32 t = 0.0f;

  /* Initialize library + device */
  gc_initialize(0);
  memset(&fmt, 0, sizeof(ga_Format));
  fmt.bitsPerSample = 16;
  fmt.numChannels = 2;
  fmt.sampleRate = 44100;
  numSamples = 2048;
  sampleSize = ga_format_sampleSize(&fmt);
  dev = ga_device_open(GA_DEVICE_TYPE_DEFAULT, 2, 2048, &fmt);
  if(!dev)
    return 1;

  /* Allocate buffer */
  buf = (gc_int16*)malloc(numSamples * sampleSize);

  /* Infinite mix loop */
  while(1)
  {
    numToQueue = ga_device_check(dev);
    while(numToQueue--)
    {
      for(i = 0; i < numSamples * 2; i = i + 2)
      {
        sample = (gc_int16)(sin(t) * 32768);
        sample = (sample > -32768 ? (sample < 32767 ? sample : 32767) : -32768);
        pan = (gc_float32)sin(t / 300) / 2.0f + 0.5f;
        buf[i] = (gc_int16)(sample * pan);
        buf[i + 1] = (gc_int16)(sample * (1.0f - pan));
        t = t + 0.03f;
        if(t > 3.14159265f)
          t -= 3.14159265f;
      }
      ga_device_queue(dev, (char*)buf);
    }
  }

  /* Clean up device + library */
  ga_device_close(dev);
  gc_shutdown();

  /* Free buffer */
  free(buf);

  return 0;
}
Exemple #7
0
Fichier : ga.c Projet : Botyto/Core
/* Sound Functions */
ga_Sound* ga_sound_create(ga_Memory* in_memory, ga_Format* in_format)
{
  ga_Sound* ret = gcX_ops->allocFunc(sizeof(ga_Sound));
  ret->numSamples = ga_memory_size(in_memory) / ga_format_sampleSize(in_format);
  memcpy(&ret->format, in_format, sizeof(ga_Format));
  ga_memory_acquire(in_memory);
  ret->memory = in_memory;
  ret->refMutex = gc_mutex_create();
  ret->refCount = 1;
  return (ga_Sound*)ret;
}
Exemple #8
0
Fichier : ga.c Projet : Botyto/Core
gc_result ga_mixer_mix(ga_Mixer* in_mixer, void* out_buffer)
{
  gc_int32 i;
  ga_Mixer* m = in_mixer;
  gc_Link* link;
  gc_int32 end = m->numSamples * m->format.numChannels;
  ga_Format* fmt = &m->format;
  gc_int32 mixSampleSize = ga_format_sampleSize(&m->mixFormat);
  memset(&m->mixBuffer[0], 0, m->numSamples * mixSampleSize);

  link = m->mixList.next;
  while(link != &m->mixList)
  {
    ga_Handle* h = (ga_Handle*)link->data;
    gc_Link* oldLink = link;
    link = link->next;
    gaX_mixer_mix_handle(m, (ga_Handle*)h, m->numSamples);
    if(ga_handle_finished(h))
    {
      gc_mutex_lock(m->mixMutex);
      gc_list_unlink(oldLink);
      gc_mutex_unlock(m->mixMutex);
    }
  }

  switch(fmt->bitsPerSample) /* mixBuffer will already be correct bps */
  {
  case 8:
    {
      gc_int8* mix = (gc_int8*)out_buffer;
      for(i = 0; i < end; ++i)
      {
        gc_int32 sample = m->mixBuffer[i];
        mix[i] = (gc_int8)(sample > -128 ? (sample < 127 ? sample : 127) : -128);
      }
      break;
    }
  case 16:
    {
      gc_int16* mix = (gc_int16*)out_buffer;
      for(i = 0; i < end; ++i)
      {
        gc_int32 sample = m->mixBuffer[i];
        mix[i] = (gc_int16)(sample > -32768 ? (sample < 32767 ? sample : 32767) : -32768);
      }
      break;
    }
  }
  return GC_SUCCESS;
}
Exemple #9
0
void gaX_stream_onSeek(gc_int32 in_sample, gc_int32 in_delta, void* in_seekContext)
{
  ga_BufferedStream* s = (ga_BufferedStream*)in_seekContext;
  gc_int32 samplesAvail, sampleSize;
  ga_Format fmt;
  ga_sample_source_format(s->innerSrc, &fmt);
  sampleSize = ga_format_sampleSize(&fmt);
  gc_mutex_lock(s->readMutex);
  gc_mutex_lock(s->seekMutex);
  samplesAvail = gc_buffer_bytesAvail(s->buffer) / sampleSize;
  gauX_tell_jump_push(&s->tellJumps, samplesAvail + in_sample, in_delta);
  gc_mutex_unlock(s->seekMutex);
  gc_mutex_unlock(s->readMutex);
}
Exemple #10
0
static gc_int32 gauX_mixThreadFunc(void* in_context)
{
  gau_Manager* ctx = (gau_Manager*)in_context;
  ga_Mixer* m = ctx->mixer;
  gc_int32 sampleSize = ga_format_sampleSize(&ctx->format);
  while(!ctx->killThreads)
  {
    gc_int32 numToQueue = ga_device_check(ctx->device);
    while(numToQueue--)
    {
      ga_mixer_mix(m, ctx->mixBuffer);
      ga_device_queue(ctx->device, ctx->mixBuffer);
    }
    gc_thread_sleep(5);
  }
  return 0;
}
Exemple #11
0
Fichier : ga.c Projet : Botyto/Core
/* Mixer Functions */
ga_Mixer* ga_mixer_create(ga_Format* in_format, gc_int32 in_numSamples)
{
  ga_Mixer* ret = gcX_ops->allocFunc(sizeof(ga_Mixer));
  gc_int32 mixSampleSize;
  gc_list_head(&ret->dispatchList);
  gc_list_head(&ret->mixList);
  ret->numSamples = in_numSamples;
  memcpy(&ret->format, in_format, sizeof(ga_Format));
  ret->mixFormat.bitsPerSample = 32;
  ret->mixFormat.numChannels = in_format->numChannels;
  ret->mixFormat.sampleRate = in_format->sampleRate;
  mixSampleSize = ga_format_sampleSize(&ret->mixFormat);
  ret->mixBuffer = (gc_int32*)gcX_ops->allocFunc(in_numSamples * mixSampleSize);
  ret->dispatchMutex = gc_mutex_create();
  ret->mixMutex = gc_mutex_create();
  return ret;
}
Exemple #12
0
Fichier : ga.c Projet : Botyto/Core
void gaX_mixer_mix_buffer(ga_Mixer* in_mixer,
                          void* in_srcBuffer, gc_int32 in_srcSamples, ga_Format* in_srcFmt,
                          gc_int32* in_dstBuffer, gc_int32 in_dstSamples, ga_Format* in_dstFmt,
                          gc_float32 in_gain, gc_float32 in_pan, gc_float32 in_pitch)
{
  ga_Format* mixFmt = in_dstFmt;
  gc_int32 mixerChannels = mixFmt->numChannels;
  gc_int32 srcChannels = in_srcFmt->numChannels;
  gc_float32 sampleScale = in_srcFmt->sampleRate / (gc_float32)mixFmt->sampleRate * in_pitch;
  gc_int32* dst = in_dstBuffer;
  gc_int32 numToFill = in_dstSamples;
  gc_float32 fj = 0.0f;
  gc_int32 j = 0;
  gc_int32 i = 0;
  gc_float32 pan = in_pan;
  gc_float32 gain = in_gain;
  gc_float32 srcSamplesRead = 0.0f;
  gc_int32 sampleSize = ga_format_sampleSize(in_srcFmt);
  pan = (pan + 1.0f) / 2.0f;
  pan = pan > 1.0f ? 1.0f : pan;
  pan = pan < 0.0f ? 0.0f : pan;

  /* TODO: Support 8-bit/16-bit mono/stereo mixer format */
  switch(in_srcFmt->bitsPerSample)
  {
  case 16:
    {
      gc_int32 srcBytes = in_srcSamples * sampleSize;
      const gc_int16* src = (const gc_int16*)in_srcBuffer;
      while(i < numToFill * (gc_int32)mixerChannels && srcBytes >= 2 * srcChannels)
      {
        gc_int32 newJ, deltaSrcBytes;
        dst[i] += (gc_int32)((gc_int32)src[j] * gain * (1.0f - pan) * 2);
        dst[i + 1] += (gc_int32)((gc_int32)src[j + ((srcChannels == 1) ? 0 : 1)] * gain * pan * 2);
        i += mixerChannels;
        fj += sampleScale * srcChannels;
        srcSamplesRead += sampleScale * srcChannels;
        newJ = (gc_uint32)fj & (srcChannels == 1 ? ~0 : ~0x1);
        deltaSrcBytes = (newJ - j) * 2;
        j = newJ;
        srcBytes -= deltaSrcBytes;
      }
      break;
    }
  }
}
Exemple #13
0
gc_int32 ga_stream_read(ga_BufferedStream* in_stream, void* in_dst, gc_int32 in_numSamples)
{
  ga_BufferedStream* s = in_stream;
  gc_CircBuffer* b = s->buffer;
  gc_int32 delta;

  /* Read the samples */
  gc_int32 samplesConsumed = 0;
  gc_mutex_lock(s->readMutex);
  {
    void* dataA;
    void* dataB;
    gc_uint32 sizeA, sizeB;
    gc_int32 totalBytes = 0;
    gc_int32 sampleSize = ga_format_sampleSize(&s->format);
    gc_int32 dstBytes = in_numSamples * sampleSize;
    gc_int32 avail = gc_buffer_bytesAvail(b);
    dstBytes = dstBytes > avail ? avail : dstBytes;
    if(gc_buffer_getAvail(b, dstBytes, &dataA, &sizeA, &dataB, &sizeB) >= 1)
    {
      gc_int32 bytesToRead = dstBytes < (gc_int32)sizeA ? dstBytes : (gc_int32)sizeA;
      memcpy(in_dst, dataA, bytesToRead);
      totalBytes += bytesToRead;
      if(dstBytes > 0 && dataB)
      {
        gc_int32 dstBytesLeft = dstBytes - bytesToRead;
        bytesToRead = dstBytesLeft < (gc_int32)sizeB ? dstBytesLeft : (gc_int32)sizeB;
        memcpy((char*)in_dst + totalBytes, dataB, bytesToRead);
        totalBytes += bytesToRead;
      }
    }
    samplesConsumed = totalBytes / sampleSize;
    gc_buffer_consume(b, totalBytes);
  }

  /* Update the tell pos */
  gc_mutex_lock(s->seekMutex);
  s->tell += samplesConsumed;
  delta = gauX_tell_jump_process(&s->tellJumps, samplesConsumed);
  s->tell += delta;
  gc_mutex_unlock(s->seekMutex);
  gc_mutex_unlock(s->readMutex);
  return samplesConsumed;
}
Exemple #14
0
gau_Manager* gau_manager_create_custom(gc_int32 in_devType,
                                       gc_int32 in_threadPolicy,
                                       gc_int32 in_numBuffers,
                                       gc_int32 in_bufferSamples)
{
  gau_Manager* ret = gcX_ops->allocFunc(sizeof(gau_Manager));

  assert(in_threadPolicy == GAU_THREAD_POLICY_SINGLE ||
         in_threadPolicy == GAU_THREAD_POLICY_MULTI);
  assert(in_bufferSamples > 128);
  assert(in_numBuffers >= 2);

  /* Open device */
  memset(&ret->format, 0, sizeof(ga_Format));
  ret->format.bitsPerSample = 16;
  ret->format.numChannels = 2;
  ret->format.sampleRate = 44100;
  ret->device = ga_device_open(in_devType, in_numBuffers, in_bufferSamples, &ret->format);
  assert(ret->device);

  /* Initialize mixer */
  ret->mixer = ga_mixer_create(&ret->format, in_bufferSamples);
  ret->streamMgr = ga_stream_manager_create();
  ret->sampleSize = ga_format_sampleSize(&ret->format);
  ret->mixBuffer = (gc_int16*)gcX_ops->allocFunc(ret->mixer->numSamples * ret->sampleSize);

  /* Create and run mixer and stream threads */
  ret->threadPolicy = in_threadPolicy;
  ret->killThreads = 0;
  if(ret->threadPolicy == GAU_THREAD_POLICY_MULTI)
  {
    ret->mixThread = gc_thread_create(gauX_mixThreadFunc, ret, GC_THREAD_PRIORITY_HIGH, 64 * 1024);
    ret->streamThread = gc_thread_create(gauX_streamThreadFunc, ret, GC_THREAD_PRIORITY_HIGH, 64 * 1024);
    gc_thread_run(ret->mixThread);
    gc_thread_run(ret->streamThread);
  }
  else
  {
    ret->mixThread = 0;
    ret->streamThread = 0;
  }

  return ret;
}
Exemple #15
0
void ga_stream_produce(ga_BufferedStream* in_stream)
{
  ga_BufferedStream* s = in_stream;
  gc_CircBuffer* b = s->buffer;
  gc_int32 sampleSize = ga_format_sampleSize(&s->format);
  gc_int32 bytesFree = gc_buffer_bytesFree(b);
  if(s->seek >= 0)
  {
    gc_int32 samplePos;
    gc_mutex_lock(s->readMutex);
    gc_mutex_lock(s->seekMutex);
    if(s->seek >= 0) /* Check again now that we're mutexed */
    {
      samplePos = s->seek;
      s->tell = samplePos;
      s->seek = -1;
      s->nextSample = samplePos;
      ga_sample_source_seek(s->innerSrc, samplePos);
      gc_buffer_consume(s->buffer, gc_buffer_bytesAvail(s->buffer)); /* Clear buffer */
      gauX_tell_jump_clear(&s->tellJumps); /* Clear tell-jump list */
    }
    gc_mutex_unlock(s->seekMutex);
    gc_mutex_unlock(s->readMutex);
  }

  while(bytesFree)
  {
    gc_int32 samplesWritten = 0;
    gc_int32 bytesWritten = 0;
    gc_int32 bytesToWrite = bytesFree;
    samplesWritten = gaX_read_samples_into_stream(s, b, bytesToWrite / sampleSize, s->innerSrc);
    bytesWritten = samplesWritten * sampleSize;
    bytesFree -= bytesWritten;
    s->nextSample += samplesWritten;
    if(bytesWritten < bytesToWrite && ga_sample_source_end(s->innerSrc))
    {
      s->end = 1;
      break;
    }
  }
}
Exemple #16
0
ga_SampleSource* gau_sample_source_create_sound(ga_Sound* in_sound)
{
  gau_SampleSourceSound* ret = gcX_ops->allocFunc(sizeof(gau_SampleSourceSound));
  gau_SampleSourceSoundContext* ctx = &ret->context;
  gc_int32 sampleSize;
  ga_sample_source_init(&ret->sampleSrc);
  ga_sound_acquire(in_sound);
  ga_sound_format(in_sound, &ret->sampleSrc.format);
  sampleSize = ga_format_sampleSize(&ret->sampleSrc.format);
  ctx->posMutex = gc_mutex_create();
  ctx->sound = in_sound;
  ctx->sampleSize = sampleSize;
  ctx->numSamples = ga_sound_numSamples(in_sound);
  ctx->pos = 0;
  ret->sampleSrc.flags = GA_FLAG_THREADSAFE | GA_FLAG_SEEKABLE;
  ret->sampleSrc.readFunc = &gauX_sample_source_sound_read;
  ret->sampleSrc.endFunc = &gauX_sample_source_sound_end;
  ret->sampleSrc.seekFunc = &gauX_sample_source_sound_seek;
  ret->sampleSrc.tellFunc = &gauX_sample_source_sound_tell;
  ret->sampleSrc.closeFunc = &gauX_sample_source_sound_close;
  return (ga_SampleSource*)ret;
}
Exemple #17
0
ga_SampleSource* gau_sample_source_create_wav(ga_DataSource* in_dataSrc)
{
  gc_result validHeader;
  gau_SampleSourceWav* ret = gcX_ops->allocFunc(sizeof(gau_SampleSourceWav));
  gau_SampleSourceWavContext* ctx = &ret->context;
  gc_int32 seekable = ga_data_source_flags(in_dataSrc) & GA_FLAG_SEEKABLE ? 1 : 0;
  ga_sample_source_init(&ret->sampleSrc);
  ret->sampleSrc.flags = GA_FLAG_THREADSAFE;
  if(seekable)
    ret->sampleSrc.flags |= GA_FLAG_SEEKABLE;
  ret->sampleSrc.readFunc = &gauX_sample_source_wav_read;
  ret->sampleSrc.endFunc = &gauX_sample_source_wav_end;
  if(seekable)
  {
    ret->sampleSrc.seekFunc = &gauX_sample_source_wav_seek;
    ret->sampleSrc.tellFunc = &gauX_sample_source_wav_tell;
  }
  ret->sampleSrc.closeFunc = &gauX_sample_source_wav_close;
  ctx->pos = 0;
  ga_data_source_acquire(in_dataSrc);
  ctx->dataSrc = in_dataSrc;
  validHeader = gauX_sample_source_wav_load_header(in_dataSrc, &ctx->wavHeader);
  if(validHeader == GC_SUCCESS)
  {
    ctx->posMutex = gc_mutex_create();
    ret->sampleSrc.format.numChannels = ctx->wavHeader.channels;
    ret->sampleSrc.format.bitsPerSample = ctx->wavHeader.bitsPerSample;
    ret->sampleSrc.format.sampleRate = ctx->wavHeader.sampleRate;
    ctx->sampleSize = ga_format_sampleSize(&ret->sampleSrc.format);
  }
  else
  {
    ga_data_source_release(in_dataSrc);
    gcX_ops->freeFunc(ret);
    ret = 0;
  }
  return (ga_SampleSource*)ret;
}
ga_DeviceImpl_XAudio2* gaX_device_open_xaudio2(gc_int32 in_numBuffers, gc_int32 in_numSamples, ga_Format* in_format)
{
  ga_DeviceImpl_XAudio2* ret = gcX_ops->allocFunc(sizeof(ga_DeviceImpl_XAudio2));
  HRESULT result;
  WAVEFORMATEX fmt;
  gc_int32 i;
  ret->devType = GA_DEVICE_TYPE_XAUDIO2;
  ret->numBuffers = in_numBuffers;
  ret->numSamples = in_numSamples;
  memcpy(&ret->format, in_format, sizeof(ga_Format));
  ret->sampleSize = ga_format_sampleSize(in_format);
  ret->nextBuffer = 0;
  ret->xa = 0;
  ret->master = 0;

  CoInitializeEx(NULL, COINIT_MULTITHREADED);
  result = XAudio2Create(&ret->xa, 0, XAUDIO2_DEFAULT_PROCESSOR);
  if(FAILED(result))
    goto cleanup;

  result = IXAudio2_CreateMasteringVoice(ret->xa, &ret->master, 2, 44100, 0, 0, 0);
  if(FAILED(result))
    goto cleanup;

  fmt.cbSize = sizeof(WAVEFORMATEX);
  ZeroMemory(&fmt, sizeof(WAVEFORMATEX));
  fmt.cbSize = sizeof(WAVEFORMATEX);
  fmt.wFormatTag = WAVE_FORMAT_PCM;
  fmt.nChannels = 2;
  fmt.wBitsPerSample = 16;
  fmt.nSamplesPerSec = 44100;
  fmt.nBlockAlign = fmt.nChannels * (fmt.wBitsPerSample / 8);
  fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;

  result = IXAudio2_CreateSourceVoice(ret->xa, &ret->source, &fmt, XAUDIO2_VOICE_NOPITCH, XAUDIO2_DEFAULT_FREQ_RATIO, 0, 0, 0);
  if(FAILED(result))
    goto cleanup;

  result =IXAudio2_StartEngine(ret->xa);
  if(FAILED(result))
    goto cleanup;

  result = IXAudio2SourceVoice_Start(ret->source, 0, XAUDIO2_COMMIT_NOW);
  if(FAILED(result))
    goto cleanup;

  ret->buffers = gcX_ops->allocFunc(ret->numBuffers * sizeof(void*));
  for(i = 0; i < ret->numBuffers; ++i)
    ret->buffers[i] = gcX_ops->allocFunc(ret->numSamples * ret->sampleSize);

  return ret;

cleanup:
  if(ret->source)
  {
    IXAudio2SourceVoice_Stop(ret->source, 0, XAUDIO2_COMMIT_NOW);
    IXAudio2SourceVoice_FlushSourceBuffers(ret->source);
    IXAudio2SourceVoice_DestroyVoice(ret->source);
  }
  if(ret->xa)
    IXAudio2_StopEngine(ret->xa);
  if(ret->master)
    IXAudio2MasteringVoice_DestroyVoice(ret->master);
  if(ret->xa)
    IXAudio2_Release(ret->xa);
  CoUninitialize();
  gcX_ops->freeFunc(ret);
  return 0;
}
Exemple #19
0
Fichier : ga.c Projet : Botyto/Core
gc_int32 ga_sound_numSamples(ga_Sound* in_sound)
{
  return ga_memory_size(in_sound->memory) / ga_format_sampleSize(&in_sound->format);
}
Exemple #20
0
gc_int32 ga_stream_ready(ga_BufferedStream* in_stream, gc_int32 in_numSamples)
{
  ga_BufferedStream* s = in_stream;
  gc_int32 avail = gc_buffer_bytesAvail(s->buffer);
  return s->end || avail >= in_numSamples * ga_format_sampleSize(&s->format) && avail > s->bufferSize / 2.0f;
}
Exemple #21
0
Fichier : ga.c Projet : Botyto/Core
void gaX_mixer_mix_handle(ga_Mixer* in_mixer, ga_Handle* in_handle, gc_int32 in_numSamples)
{
  ga_Handle* h = in_handle;

  ga_Mixer* m = in_mixer;
  ga_SampleSource* ss = h->sampleSrc;
  if(ga_sample_source_end(ss))
  {
    /* Stream is finished! */
    gc_mutex_lock(h->handleMutex);
    if(h->state < GA_HANDLE_STATE_FINISHED)
      h->state = GA_HANDLE_STATE_FINISHED;
    gc_mutex_unlock(h->handleMutex);
    return;
  }
  else
  {
    if(h->state == GA_HANDLE_STATE_PLAYING)
    {
      ga_Format handleFormat;
      ga_sample_source_format(ss, &handleFormat);
      {
        /* Check if we have enough samples to stream a full buffer */
        gc_int32 srcSampleSize = ga_format_sampleSize(&handleFormat);
        gc_int32 dstSampleSize = ga_format_sampleSize(&m->format);
        gc_float32 oldPitch = h->pitch;
        gc_float32 dstToSrc = handleFormat.sampleRate / (gc_float32)m->format.sampleRate * oldPitch;
        gc_int32 requested = (gc_int32)(in_numSamples * dstToSrc);
        requested = requested / dstToSrc < in_numSamples ? requested + 1 : requested;
        if(requested > 0 && ga_sample_source_ready(ss, requested))
        {
          gc_float32 gain, pan, pitch;
          gc_int32* dstBuffer;
          gc_int32 dstSamples;

          gc_mutex_lock(h->handleMutex);
          gain = h->gain;
          pan = h->pan;
          pitch = h->pitch;
          gc_mutex_unlock(h->handleMutex);

          /* We avoided a mutex lock by using pitch to check if buffer has enough dst samples */
          /* If it has changed since then, we re-test to make sure we still have enough samples */
          if(oldPitch != pitch)
          {
            dstToSrc = handleFormat.sampleRate / (gc_float32)m->format.sampleRate * pitch;
            requested = (gc_int32)(in_numSamples * dstToSrc);
            requested = requested / dstToSrc < in_numSamples ? requested + 1 : requested;
            if(!(requested > 0 && ga_sample_source_ready(ss, requested)))
              return;
          }

          dstBuffer = &m->mixBuffer[0];
          dstSamples = in_numSamples;
          {
            /* TODO: To optimize, we can refactor the _read() interface to be _mix(), avoiding this malloc/copy */
            gc_int32 bufferSize = requested * srcSampleSize;
            void* src = gcX_ops->allocFunc(bufferSize);
            gc_int32 dstBytes = dstSamples * dstSampleSize;
            gc_int32 numRead = 0;
            numRead = ga_sample_source_read(ss, src, requested, 0, 0);
            gaX_mixer_mix_buffer(in_mixer,
                                 src, numRead, &handleFormat,
                                 dstBuffer, dstSamples, &m->format,
                                 gain, pan, pitch);
            gcX_ops->freeFunc(src);
          }
        }
      }
    }
  }
}