gaX_StreamLink* gaX_stream_link_create() { gaX_StreamLink* ret = (gaX_StreamLink*)gcX_ops->allocFunc(sizeof(gaX_StreamLink)); ret->refCount = 1; ret->refMutex = gc_mutex_create(); ret->produceMutex = gc_mutex_create(); ret->stream = 0; return ret; }
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; }
/* Stream Manager */ ga_StreamManager* ga_stream_manager_create() { ga_StreamManager* ret = (ga_StreamManager*)gcX_ops->allocFunc(sizeof(ga_StreamManager)); ret->streamListMutex = gc_mutex_create(); gc_list_head(&ret->streamList); return ret; }
/* 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; }
/* Data Source Structure */ void ga_data_source_init(ga_DataSource* in_dataSrc) { in_dataSrc->refCount = 1; in_dataSrc->readFunc = 0; in_dataSrc->seekFunc = 0; in_dataSrc->tellFunc = 0; in_dataSrc->closeFunc = 0; in_dataSrc->flags = 0; in_dataSrc->refMutex = gc_mutex_create(); }
/* 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; }
/* Handle Functions */ void gaX_handle_init(ga_Handle* in_handle, ga_Mixer* in_mixer) { ga_Handle* h = in_handle; h->state = GA_HANDLE_STATE_INITIAL; h->mixer = in_mixer; h->callback = 0; h->context = 0; h->gain = 1.0f; h->pitch = 1.0f; h->pan = 0.0f; h->handleMutex = gc_mutex_create(); }
/* Sample Source Structure */ void ga_sample_source_init(ga_SampleSource* in_sampleSrc) { in_sampleSrc->refCount = 1; in_sampleSrc->readFunc = 0; in_sampleSrc->endFunc = 0; in_sampleSrc->readyFunc = 0; in_sampleSrc->seekFunc = 0; in_sampleSrc->tellFunc = 0; in_sampleSrc->closeFunc = 0; in_sampleSrc->flags = 0; in_sampleSrc->refMutex = gc_mutex_create(); }
/* 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; }
ga_DataSource* gau_data_source_create_memory(ga_Memory* in_memory) { gau_DataSourceMemory* ret = gcX_ops->allocFunc(sizeof(gau_DataSourceMemory)); ga_data_source_init(&ret->dataSrc); ret->dataSrc.flags = GA_FLAG_SEEKABLE | GA_FLAG_THREADSAFE; ret->dataSrc.readFunc = &gauX_data_source_memory_read; ret->dataSrc.seekFunc = &gauX_data_source_memory_seek; ret->dataSrc.tellFunc = &gauX_data_source_memory_tell; ret->dataSrc.closeFunc = &gauX_data_source_memory_close; ga_memory_acquire(in_memory); ret->context.memory = in_memory; ret->context.pos = 0; ret->context.memMutex = gc_mutex_create(); return (ga_DataSource*)ret; }
/* Memory Functions */ static ga_Memory* gaX_memory_create(void* in_data, gc_int32 in_size, gc_int32 in_copy) { ga_Memory* ret = gcX_ops->allocFunc(sizeof(ga_Memory)); ret->size = in_size; if(in_copy) { ret->data = gcX_ops->allocFunc(in_size); memcpy(ret->data, in_data, in_size); } else ret->data = in_data; ret->refMutex = gc_mutex_create(); ret->refCount = 1; return (ga_Memory*)ret; }
ga_DataSource* gau_data_source_create_file(const char* in_filename) { gau_DataSourceFile* ret = gcX_ops->allocFunc(sizeof(gau_DataSourceFile)); ga_data_source_init(&ret->dataSrc); ret->dataSrc.flags = GA_FLAG_SEEKABLE | GA_FLAG_THREADSAFE; ret->dataSrc.readFunc = &gauX_data_source_file_read; ret->dataSrc.seekFunc = &gauX_data_source_file_seek; ret->dataSrc.tellFunc = &gauX_data_source_file_tell; ret->dataSrc.closeFunc = &gauX_data_source_file_close; ret->context.f = fopen(in_filename, "rb"); if(ret->context.f) ret->context.fileMutex = gc_mutex_create(); else { gcX_ops->freeFunc(ret); ret = 0; } return (ga_DataSource*)ret; }
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; }
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_DataSource* gau_data_source_create_file_arc(const char* in_filename, gc_int32 in_offset, gc_int32 in_size) { gau_DataSourceFileArc* ret = gcX_ops->allocFunc(sizeof(gau_DataSourceFileArc)); ga_data_source_init(&ret->dataSrc); ret->dataSrc.flags = GA_FLAG_SEEKABLE | GA_FLAG_THREADSAFE; ret->dataSrc.readFunc = &gauX_data_source_file_arc_read; ret->dataSrc.seekFunc = &gauX_data_source_file_arc_seek; ret->dataSrc.tellFunc = &gauX_data_source_file_arc_tell; ret->dataSrc.closeFunc = &gauX_data_source_file_arc_close; ret->context.offset = in_offset; ret->context.size = in_size; ret->context.f = fopen(in_filename, "rb"); if(ret->context.f && in_size >= 0) { ret->context.fileMutex = gc_mutex_create(); fseek(ret->context.f, in_offset, SEEK_SET); } else { gcX_ops->freeFunc(ret); ret = 0; } return (ga_DataSource*)ret; }
ga_SampleSource* gau_sample_source_create_ogg(ga_DataSource* in_dataSrc) { gau_SampleSourceOgg* ret = gcX_ops->allocFunc(sizeof(gau_SampleSourceOgg)); gau_SampleSourceOggContext* ctx = &ret->context; gc_int32 endian = 0; /* 0 is little endian (aka x86), 1 is big endian */ gc_int32 bytesPerSample = 2; gc_int32 isValidOgg = 0; gc_int32 oggIsOpen; ov_callbacks oggCallbacks; 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_ogg_read; ret->sampleSrc.endFunc = &gauX_sample_source_ogg_end; if(seekable) { ret->sampleSrc.seekFunc = &gauX_sample_source_ogg_seek; ret->sampleSrc.tellFunc = &gauX_sample_source_ogg_tell; } ret->sampleSrc.closeFunc = &gauX_sample_source_ogg_close; ga_data_source_acquire(in_dataSrc); ctx->dataSrc = in_dataSrc; ctx->endOfSamples = 0; /* OGG Setup */ oggCallbacks.read_func = &gauX_sample_source_ogg_callback_read; if(seekable) { oggCallbacks.seek_func = &gauX_sample_source_ogg_callback_seek; oggCallbacks.tell_func = &gauX_sample_source_ogg_callback_tell; } else { oggCallbacks.seek_func = 0; oggCallbacks.tell_func = 0; } oggCallbacks.close_func = &gauX_sample_source_ogg_callback_close; ctx->oggCallbackData.dataSrc = in_dataSrc; oggIsOpen = ov_open_callbacks(&ctx->oggCallbackData, &ctx->oggFile, 0, 0, oggCallbacks); if(oggIsOpen == 0) /* 0 means "open" */ { ctx->oggInfo = ov_info(&ctx->oggFile, -1); ov_pcm_seek(&ctx->oggFile, 0); /* Seek fixes some poorly-formatted OGGs. */ isValidOgg = ctx->oggInfo->channels <= 2; if(isValidOgg) { ret->sampleSrc.format.bitsPerSample = bytesPerSample * 8; ret->sampleSrc.format.numChannels = ctx->oggInfo->channels; ret->sampleSrc.format.sampleRate = ctx->oggInfo->rate; } else ov_clear(&ctx->oggFile); } if(isValidOgg) ctx->oggMutex = gc_mutex_create(); else { ga_data_source_release(in_dataSrc); gcX_ops->freeFunc(ret); ret = 0; } return (ga_SampleSource*)ret; }