예제 #1
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;
}
예제 #2
0
파일: ga.c 프로젝트: 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;
}
예제 #3
0
파일: gau.c 프로젝트: dazzlex27/S3DGE
gc_int32 gauX_sample_source_loop_read(void* in_context, void* in_dst, gc_int32 in_numSamples,
                                      tOnSeekFunc in_onSeekFunc, void* in_seekContext)
{
  gau_SampleSourceLoopContext* ctx = &((gau_SampleSourceLoop*)in_context)->context;
  gc_int32 numRead = 0;
  gc_int32 triggerSample, targetSample;
  gc_int32 pos, total;
  gc_int32 sampleSize;
  gc_int32 totalRead = 0;
  ga_SampleSource* ss = ctx->innerSrc;
  gc_mutex_lock(ctx->loopMutex);
  triggerSample = ctx->triggerSample;
  targetSample = ctx->targetSample;
  gc_mutex_unlock(ctx->loopMutex);
  pos = ga_sample_source_tell(ss, &total);
  if((targetSample < 0 && triggerSample <= 0))
    return ga_sample_source_read(ss, in_dst, in_numSamples, 0, 0);
  if(triggerSample <= 0)
    triggerSample = total;
  if(pos > triggerSample)
    return ga_sample_source_read(ss, in_dst, in_numSamples, 0, 0);
  sampleSize = ctx->sampleSize;
  while(in_numSamples)
  {
    gc_int32 avail = triggerSample - pos;
    gc_int32 doSeek = avail <= in_numSamples;
    gc_int32 toRead = doSeek ? avail : in_numSamples;
    numRead = ga_sample_source_read(ss, in_dst,  toRead, 0, 0);
    totalRead += numRead;
    in_numSamples -= numRead;
    in_dst = (char*)in_dst + numRead * sampleSize;
    if(doSeek && toRead == numRead)
    {
      ga_sample_source_seek(ss, targetSample);
      ++ctx->loopCount;
      if(in_onSeekFunc)
        in_onSeekFunc(totalRead, targetSample - triggerSample, in_seekContext);
    }
    pos = ga_sample_source_tell(ss, &total);
  }
  return totalRead;
}
예제 #4
0
파일: ga.c 프로젝트: 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);
          }
        }
      }
    }
  }
}