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 render(void) { int width, height, active; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT); loop = xm_get_loop_count(xmctx); for(uint16_t i = 1; i <= channels; ++i) { active = xm_is_channel_active(xmctx, i); glUniform4f(xmdatau, (float)i / (float)channels, active ? (float)xm_get_instrument_of_channel(xmctx, i) / (float)instruments : 0.f, active ? log2f(xm_get_frequency_of_channel(xmctx, i)) : 0.f, active ? xm_get_volume_of_channel(xmctx, i) : 0.f ); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); } }
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; }