int main(int argc, char** argv) { xm_context_t* ctx; float buffer[buffer_size]; if(argc != 2) FATAL("Usage: %s <filename>\n", argv[0]); create_context_from_file(&ctx, rate, argv[1]); xm_set_max_loop_count(ctx, 1); puts_uint32_be(0x2E736E64); /* .snd magic number */ puts_uint32_be(24); /* Header size */ puts_uint32_be((uint32_t)(-1)); /* Data size, unknown */ puts_uint32_be(6); /* Encoding: 32-bit IEEE floating point */ puts_uint32_be(rate); /* Sample rate */ puts_uint32_be(channels); /* Number of interleaved channels */ while(xm_get_loop_count(ctx) == 0) { xm_generate_samples(ctx, buffer, sizeof(buffer) / (channels * sizeof(float))); for(size_t k = 0; k < buffer_size; ++k) { union { float f; uint32_t i; } u; u.f = buffer[k]; puts_uint32_be(u.i); } } xm_free_context(ctx); return 0; }
void teardown(void) { snd_pcm_drop(device); snd_pcm_close(device); xm_free_context(xmctx); glfwDestroyWindow(window); glfwTerminate(); }
int main(int argc, char** argv) { xm_context_t* ctx; FILE* out; uint32_t num_samples = 0; float buffer[buffer_size]; if(argc != 3) FATAL("Usage: %s <xm-file-input> <wav-file-out>\n", argv[0]); create_context_from_file(&ctx, rate, argv[1]); if(ctx == NULL) exit(1); xm_set_max_loop_count(ctx, 1); out = fopen(argv[2], "w"); if(out == NULL) FATAL_ERR("could not open output file for writing"); /* WAVE format info taken from * http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html */ /* Unlike AU, WAVE files cannot have an unknown length. This * is why we can't write directly to stdout (we need to rewind * because module length is hard to know. */ fputs("RIFF", out); puts_uint32_le(0, out); /* Chunk size. Will be filled later. */ fputs("WAVE", out); fputs("fmt ", out); /* Start format chunk */ puts_uint32_le(16, out); /* Format chunk size */ puts_uint16_le(3, out); /* IEEE float sample data */ puts_uint16_le(channels, out); /* Number of channels */ puts_uint32_le(rate, out); /* Frames/sec (sampling rate) */ puts_uint32_le(rate * channels * sizeof(float), out); /* nAvgBytesPerSec ? */ puts_uint16_le(channels * sizeof(float), out); /* nBlockAlign ? */ puts_uint16_le(8 * sizeof(float), out); /* wBitsPerSample ? */ fputs("data", out); /* Start data chunk */ puts_uint32_le(0, out); /* Data chunk size. Will be filled later. */ while(xm_get_loop_count(ctx) == 0) { xm_generate_samples(ctx, buffer, buffer_size / channels); num_samples += buffer_size; for(size_t k = 0; k < buffer_size; ++k) { union { float f; uint32_t i; } u; u.f = buffer[k]; puts_uint32_le(u.i, out); } } fseek(out, 4, SEEK_SET); puts_uint32_le(36 + num_samples * sizeof(float), out); fseek(out, 32, SEEK_SET); puts_uint32_le(num_samples * sizeof(float), out); fclose(out); xm_free_context(ctx); 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; }