#include &lt;stdio.h&gt;
#include &lt;stdint.h&gt;
#include &lt;string.h&gt;
#include &lt;SDL2/SDL.h&gt;
#include &lt;acm/libacm.h&gt;

/* Written circa 2014 by grepwood@sucs.org */

/* This program will utilize libacm and some string logic
 * in order to absolutely correctly decode an ACM at all times,
 * without user hints. */

/* prototype for our audio callback
 * see the implementation for more information */

/* variable declarations */
static uint8_t *audio_pos; /* global pointer to the audio buffer to be played */
static uint32_t audio_len; /* remaining length of the sample we have to play */

/* audio callback function
 * here you have to copy the data of your audio buffer into the
 * requesting audio buffer (stream)
 * you should only copy as much as the requested length (len) */
 
void my_audio_callback(void * userdata, Uint8 *stream, int len) {
	if (audio_len ==0)
		return;
	len = ( (unsigned)len &gt; audio_len ? audio_len : (unsigned)len );
	SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME); /* mix from one buffer into another */

	audio_pos += len;
	audio_len -= len;
}

/* Some sounds in Fallout have spoofed channel amount.
 * Known suspects are from the Speech directory.
 * Hence the strstr call */
uint8_t DetectFakeStereo(const char *fn) {
	uint8_t result = 0;
	char * pointer;
	pointer = strstr(fn,&quot;Speech&quot;);
	if(pointer != NULL) {
		result = 1;
	}
	return result;
}

int main(int argc, char* argv[]){
	static uint32_t wav_length;
	static uint8_t *wav_buffer;
	static SDL_AudioSpec wav_spec;
	uint32_t wavsize;
	char * fn2 = NULL;
	uint8_t cf_force_chans;
	SDL_RWops * WavFromACM = NULL;
	if ( argc != 2 ) {
		fputs(&quot;Need a path to ACM file\n&quot;,stderr);
		return 2;
	}
	if (SDL_Init(SDL_INIT_AUDIO) &lt; 0) {
		fputs(&quot;Could not SDL_Init\n&quot;,stderr);
		return 1;
	}
/* Detect spoofed stereo by known strings */
	cf_force_chans = DetectFakeStereo(argv[1]);
/* FSF.ACM is unfortunately spoofed too */
	cf_force_chans = 1;
/* Convert the ACM to WAV */
	fn2 = libacm_decode_file_to_mem(argv[1],cf_force_chans,&amp;wavsize);
/* Load the WAV the specs, length and buffer of our wav are filled */
	WavFromACM = SDL_RWFromConstMem(fn2,wavsize);
	if(SDL_LoadWAV_RW(WavFromACM,1,&amp;wav_spec,&amp;wav_buffer, &amp;wav_length) == NULL) {
		free(fn2);
		fputs(&quot;Loading the ACM didn&#039;t succeed\n&quot;,stderr);
		return 2;
	}
/* set the callback function */
	wav_spec.callback = my_audio_callback;
	wav_spec.userdata = NULL;
/* set our global static variables */
	audio_pos = wav_buffer; /* copy sound buffer */
	audio_len = wav_length; /* copy file length */
/* Open the audio device */
	if ( SDL_OpenAudio(&amp;wav_spec, NULL) &lt; 0 ){
		fprintf(stderr, &quot;Couldn&#039;t open audio: %s\n&quot;, SDL_GetError());
		free(fn2);
		exit(-1);
	}
/* Start playing */
	SDL_PauseAudio(0);
/* wait until we&#039;re don&#039;t playing */
	while ( audio_len &gt; 0 ) {
		SDL_Delay(100);
	}
/* shut everything down */
	SDL_CloseAudio();
	SDL_FreeWAV(wav_buffer);
	free(fn2);
	return 0;
}
