Created By grepwood at 2014/10/11 23:28

https://sucs.org/pb/824 (plain)
  1.   #include <stdio.h>
  2.   #include <stdint.h>
  3.   #include <string.h>
  4.   #include <SDL2/SDL.h>
  5.   #include <acm/libacm.h>
  6.  
  7.   /* Written circa 2014 by grepwood@sucs.org */
  8.  
  9.   /* This program will utilize libacm and some string logic
  10.   * in order to absolutely correctly decode an ACM at all times,
  11.   * without user hints. */
  12.  
  13.   /* prototype for our audio callback
  14.   * see the implementation for more information */
  15.  
  16.   /* variable declarations */
  17.   static uint8_t *audio_pos; /* global pointer to the audio buffer to be played */
  18.   static uint32_t audio_len; /* remaining length of the sample we have to play */
  19.  
  20.   /* audio callback function
  21.   * here you have to copy the data of your audio buffer into the
  22.   * requesting audio buffer (stream)
  23.   * you should only copy as much as the requested length (len) */
  24.  
  25.   void my_audio_callback(void * userdata, Uint8 *stream, int len) {
  26.       if (audio_len ==0)
  27.           return;
  28.       len = ( (unsigned)len > audio_len ? audio_len : (unsigned)len );
  29.       SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME); /* mix from one buffer into another */
  30.  
  31.       audio_pos += len;
  32.       audio_len -= len;
  33.   }
  34.  
  35.   /* Some sounds in Fallout have spoofed channel amount.
  36.   * Known suspects are from the Speech directory.
  37.   * Hence the strstr call */
  38.   uint8_t DetectFakeStereo(const char *fn) {
  39.       uint8_t result = 0;
  40.       char * pointer;
  41.       pointer = strstr(fn,"Speech");
  42.       if(pointer != NULL) {
  43.           result = 1;
  44.       }
  45.       return result;
  46.   }
  47.  
  48.   int main(int argc, char* argv[]){
  49.       static uint32_t wav_length;
  50.       static uint8_t *wav_buffer;
  51.       static SDL_AudioSpec wav_spec;
  52.       uint32_t wavsize;
  53.       char * fn2 = NULL;
  54.       uint8_t cf_force_chans;
  55.       SDL_RWops * WavFromACM = NULL;
  56.       if ( argc != 2 ) {
  57.           fputs("Need a path to ACM file\n",stderr);
  58.           return 2;
  59.       }
  60.       if (SDL_Init(SDL_INIT_AUDIO) < 0) {
  61.           fputs("Could not SDL_Init\n",stderr);
  62.           return 1;
  63.       }
  64.   /* Detect spoofed stereo by known strings */
  65.       cf_force_chans = DetectFakeStereo(argv[1]);
  66.   /* FSF.ACM is unfortunately spoofed too */
  67.       cf_force_chans = 1;
  68.   /* Convert the ACM to WAV */
  69.       fn2 = libacm_decode_file_to_mem(argv[1],cf_force_chans,&wavsize);
  70.   /* Load the WAV the specs, length and buffer of our wav are filled */
  71.       WavFromACM = SDL_RWFromConstMem(fn2,wavsize);
  72.       if(SDL_LoadWAV_RW(WavFromACM,1,&wav_spec,&wav_buffer, &wav_length) == NULL) {
  73.           free(fn2);
  74.           fputs("Loading the ACM didn't succeed\n",stderr);
  75.           return 2;
  76.       }
  77.   /* set the callback function */
  78.       wav_spec.callback = my_audio_callback;
  79.       wav_spec.userdata = NULL;
  80.   /* set our global static variables */
  81.       audio_pos = wav_buffer; /* copy sound buffer */
  82.       audio_len = wav_length; /* copy file length */
  83.   /* Open the audio device */
  84.       if ( SDL_OpenAudio(&wav_spec, NULL) < 0 ){
  85.           fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
  86.           free(fn2);
  87.           exit(-1);
  88.       }
  89.   /* Start playing */
  90.       SDL_PauseAudio(0);
  91.   /* wait until we're don't playing */
  92.       while ( audio_len > 0 ) {
  93.           SDL_Delay(100);
  94.       }
  95.   /* shut everything down */
  96.       SDL_CloseAudio();
  97.       SDL_FreeWAV(wav_buffer);
  98.       free(fn2);
  99.       return 0;
  100.   }

You must be logged in to paste new items to the PasteBin