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; }
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; } } }
gc_int32 gauX_sample_source_loop_seek(void* in_context, gc_int32 in_sampleOffset) { gau_SampleSourceLoopContext* ctx = &((gau_SampleSourceLoop*)in_context)->context; return ga_sample_source_seek(ctx->innerSrc, in_sampleOffset); }
gc_result ga_handle_seek(ga_Handle* in_handle, gc_int32 in_sampleOffset) { ga_sample_source_seek(in_handle->sampleSrc, in_sampleOffset); return GC_SUCCESS; }