Esempio n. 1
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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
0
File: ga.c Progetto: 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;
}
Esempio n. 5
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);
}
Esempio n. 6
0
/* Stream */
ga_BufferedStream* ga_stream_create(ga_StreamManager* in_mgr, ga_SampleSource* in_sampleSrc, gc_int32 in_bufferSize)
{
  ga_BufferedStream* ret = gcX_ops->allocFunc(sizeof(ga_BufferedStream));
  ret->refCount = 1;
  ret->refMutex = gc_mutex_create();
  ga_sample_source_acquire(in_sampleSrc);
  ga_sample_source_format(in_sampleSrc, &ret->format);
  gc_list_head(&ret->tellJumps);
  ret->innerSrc = in_sampleSrc;
  ret->nextSample = 0;
  ret->seek = 0;
  ret->tell = 0;
  ret->end = 0;
  ret->bufferSize = in_bufferSize;
  ret->flags = ga_sample_source_flags(in_sampleSrc);
  assert(ret->flags & GA_FLAG_THREADSAFE);
  ret->produceMutex = gc_mutex_create();
  ret->seekMutex = gc_mutex_create();
  ret->readMutex = gc_mutex_create();
  ret->buffer = gc_buffer_create(in_bufferSize);
  ret->streamLink = (gc_Link*)gaX_stream_manager_add(in_mgr, ret);
  return ret;
}
Esempio n. 7
0
File: ga.c Progetto: 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);
          }
        }
      }
    }
  }
}
Esempio n. 8
0
File: ga.c Progetto: Botyto/Core
void ga_handle_format(ga_Handle* in_handle, ga_Format* out_format)
{
  ga_sample_source_format(in_handle->sampleSrc, out_format);
}