int xm_create_context(xm_context_t** ctxp, char* moddata, uint32_t rate) { int ret; size_t bytes_needed; char* mempool; xm_context_t* ctx; if((ret = xm_check_header_sanity(moddata))) { DEBUG("xm_check_header_sanity() returned %i", ret); return 1; } bytes_needed = xm_get_memory_needed_for_context(moddata); mempool = malloc(bytes_needed); if(mempool == NULL && bytes_needed > 0) { /* malloc() failed, trouble ahead */ DEBUG("call to malloc() failed, returned %p", mempool); return 2; } /* Initialize most of the fields to 0, 0.f, NULL or false depending on type */ memset(mempool, 0, bytes_needed); ctx = (*ctxp = (xm_context_t*)mempool); ctx->allocated_memory = mempool; /* Keep original pointer for free() */ mempool += sizeof(xm_context_t); ctx->rate = rate; mempool = xm_load_module(ctx, moddata, mempool); ctx->channels = (xm_channel_context_t*)mempool; mempool += ctx->module.num_channels * sizeof(xm_channel_context_t); ctx->global_volume = 1.f; ctx->amplification = .5f; /* Purely empirical value */ ctx->volume_ramp = (1.f / 128.f); ctx->panning_ramp = (1.f / 128.f); for(uint8_t i = 0; i < ctx->module.num_channels; ++i) { xm_channel_context_t* ch = ctx->channels + i; ch->ping = true; ch->vibrato_waveform = XM_SINE_WAVEFORM; ch->vibrato_waveform_retrigger = true; ch->tremolo_waveform = XM_SINE_WAVEFORM; ch->tremolo_waveform_retrigger = true; ch->volume = ch->volume_envelope_volume = ch->fadeout_volume = 1.0f; ch->panning = ch->panning_envelope_panning = .5f; ch->actual_volume = .0f; ch->actual_panning = .5f; } ctx->row_loop_count = (uint8_t*)mempool; mempool += MAX_NUM_ROWS * sizeof(uint8_t); return 0; }
int xm_create_context_safe(xm_context_t** ctxp, const char* moddata, size_t moddata_length, uint32_t rate) { #if XM_DEFENSIVE int ret; #endif size_t bytes_needed; char* mempool; xm_context_t* ctx; #if XM_DEFENSIVE if((ret = xm_check_sanity_preload(moddata, moddata_length))) { DEBUG("xm_check_sanity_preload() returned %i, module is not safe to load", ret); return 1; } #endif bytes_needed = xm_get_memory_needed_for_context(moddata, moddata_length); mempool = malloc(bytes_needed); if(mempool == NULL && bytes_needed > 0) { /* malloc() failed, trouble ahead */ DEBUG("call to malloc() failed, returned %p", (void*)mempool); return 2; } /* Initialize most of the fields to 0, 0.f, NULL or false depending on type */ memset(mempool, 0, bytes_needed); ctx = (*ctxp = (xm_context_t*)mempool); ctx->allocated_memory = mempool; /* Keep original pointer for free() */ mempool += sizeof(xm_context_t); ctx->rate = rate; mempool = xm_load_module(ctx, moddata, moddata_length, mempool); ctx->channels = (xm_channel_context_t*)mempool; mempool += ctx->module.num_channels * sizeof(xm_channel_context_t); ctx->global_volume = 1.f; ctx->amplification = .25f; /* XXX: some bad modules may still clip. Find out something better. */ #if XM_RAMPING ctx->volume_ramp = (1.f / 128.f); ctx->panning_ramp = (1.f / 128.f); #endif for(uint8_t i = 0; i < ctx->module.num_channels; ++i) { xm_channel_context_t* ch = ctx->channels + i; ch->ping = true; ch->vibrato_waveform = XM_SINE_WAVEFORM; ch->vibrato_waveform_retrigger = true; ch->tremolo_waveform = XM_SINE_WAVEFORM; ch->tremolo_waveform_retrigger = true; ch->volume = ch->volume_envelope_volume = ch->fadeout_volume = 1.0f; ch->panning = ch->panning_envelope_panning = .5f; ch->actual_volume = .0f; ch->actual_panning = .5f; } ctx->row_loop_count = (uint8_t*)mempool; mempool += MAX_NUM_ROWS * sizeof(uint8_t); #if XM_DEFENSIVE if((ret = xm_check_sanity_postload(ctx))) { DEBUG("xm_check_sanity_postload() returned %i, module is not safe to play", ret); xm_free_context(ctx); return 1; } #endif return 0; }