From: David Griffith Date: Thu, 19 Sep 2019 05:10:40 +0000 (-0700) Subject: Convert ux_audio.c to K&R style. X-Git-Url: https://scope-eye.net/git/?a=commitdiff_plain;h=7cf29adbbacfecdf217f91193d71367cf651ed13;p=liskon_frotz.git Convert ux_audio.c to K&R style. --- diff --git a/src/curses/ux_audio.c b/src/curses/ux_audio.c index 977a9ce..00f68b0 100644 --- a/src/curses/ux_audio.c +++ b/src/curses/ux_audio.c @@ -66,124 +66,124 @@ ux_sem_t sound_done; /* 1 if the sound is done */ #define EVENT_STOP_STREAM 2 typedef struct { - SRC_STATE *src_state; - SRC_DATA src_data; - float *scratch; - float *input; - float *output; + SRC_STATE *src_state; + SRC_DATA src_data; + float *scratch; + float *input; + float *output; } resampler_t; typedef struct { - bool active; /* If a voice is actively outputting sound*/ - int src; /* The source sound ID*/ - int type; /* The voice type 0, 1, 2..N*/ - int pos; /* The current position*/ - int repid; /* The current number of repetitions*/ + bool active; /* If a voice is actively outputting sound*/ + int src; /* The source sound ID*/ + int type; /* The voice type 0, 1, 2..N*/ + int pos; /* The current position*/ + int repid; /* The current number of repetitions*/ } sound_state_t; typedef struct { - float *samples; - int nsamples; + float *samples; + int nsamples; } sound_buffer_t; typedef enum { - FORM, - OGGV, - MOD + FORM, + OGGV, + MOD } sound_type_t; typedef struct sound_stream { - /*returns 1 if process can continue*/ - int (*process)(struct sound_stream *self, float *outl, float *outr, unsigned samples); - void (*cleanup)(struct sound_stream *self); - sound_type_t sound_type; - int id; + /* returns 1 if process can continue */ + int (*process)(struct sound_stream *self, float *outl, float *outr, unsigned samples); + void (*cleanup)(struct sound_stream *self); + sound_type_t sound_type; + int id; } sound_stream_t; typedef struct { - int (*process)(sound_stream_t *self, float *outl, float *outr, unsigned samples); - void (*cleanup)(sound_stream_t *self); - sound_type_t sound_type; - int id; + int (*process)(sound_stream_t *self, float *outl, float *outr, unsigned samples); + void (*cleanup)(sound_stream_t *self); + sound_type_t sound_type; + int id; } sound_stream_dummy_t; typedef struct { - uint8_t *data; - size_t len; - size_t pos; + uint8_t *data; + size_t len; + size_t pos; } buf_t; typedef struct { - FILE *file; - size_t base_offset; - size_t len; - size_t pos; + FILE *file; + size_t base_offset; + size_t len; + size_t pos; } file_reader_t; typedef struct { - int (*process)(sound_stream_t *self, float *outl, float *outr, unsigned samples); - void (*cleanup)(sound_stream_t *self); - sound_type_t sound_type; - int id; - - resampler_t *rsmp; - float volume; - float *floatbuffer; - - SNDFILE *sndfile; - SF_INFO sf_info; - size_t length; /* Number of samples (= smpsl.length == smpsr.length)*/ - int repeats; /* Total times to play the sample 1..n*/ - int pos; - - file_reader_t freader; + int (*process)(sound_stream_t *self, float *outl, float *outr, unsigned samples); + void (*cleanup)(sound_stream_t *self); + sound_type_t sound_type; + int id; + + resampler_t *rsmp; + float volume; + float *floatbuffer; + + SNDFILE *sndfile; + SF_INFO sf_info; + size_t length; /* Number of samples (= smpsl.length == smpsr.length) */ + int repeats; /* Total times to play the sample 1..n */ + int pos; + + file_reader_t freader; } sound_stream_aiff_t; typedef struct { - int (*process)(sound_stream_t *self, float *outl, float *outr, unsigned samples); - void (*cleanup)(sound_stream_t *self); - sound_type_t sound_type; - int id; - - char *filedata; - short *shortbuffer; - ModPlugFile *mod; - ModPlug_Settings settings; + int (*process)(sound_stream_t *self, float *outl, float *outr, unsigned samples); + void (*cleanup)(sound_stream_t *self); + sound_type_t sound_type; + int id; + + char *filedata; + short *shortbuffer; + ModPlugFile *mod; + ModPlug_Settings settings; } sound_stream_mod_t; typedef struct { - uint8_t type; - union { - sound_stream_t *e; - int i; - }; + uint8_t type; + union { + sound_stream_t *e; + int i; + }; } sound_event_t; #define NUM_VOICES 8 typedef struct { - /*Audio driver parameters*/ - size_t buffer_size; - float sample_rate; - - /*Output buffers*/ - float *outl; - float *outr; - - /*Sound parameters*/ - sound_stream_t *streams[NUM_VOICES]; /* Active streams*/ - sound_state_t voices[NUM_VOICES]; /* Max concurrent sound effects/music*/ - - /*Event (one is process per frame of audio)*/ - ux_sem_t ev_free; /*1 if an event can be submitted*/ - ux_sem_t ev_pending; /*1 if there's an event ready to be processed*/ - sound_event_t event; + /* Audio driver parameters */ + size_t buffer_size; + float sample_rate; + + /* Output buffers */ + float *outl; + float *outr; + + /* Sound parameters */ + sound_stream_t *streams[NUM_VOICES]; /* Active streams */ + sound_state_t voices[NUM_VOICES]; /* Max concurrent sound effects/music */ + + /* Event (one is process per frame of audio) */ + ux_sem_t ev_free; /* 1 if an event can be submitted */ + ux_sem_t ev_pending; /* 1 if there's an event ready to be processed */ + sound_event_t event; } sound_engine_t; static sound_engine_t frotz_audio; -/*FILE *audio_log;*/ +/* FILE *audio_log; */ /********************************************************************** * Utilities * @@ -198,41 +198,44 @@ static sound_engine_t frotz_audio; static char * getfiledata(FILE *fp, long *size) { - long offset = ftell(fp); - fseek(fp, 0L, SEEK_END); - (*size) = ftell(fp); - fseek(fp, offset, SEEK_SET); - char *data = (char*)malloc(*size); - fread(data, *size, sizeof(char), fp); - fseek(fp, offset, SEEK_SET); - return(data); + long offset = ftell(fp); + fseek(fp, 0L, SEEK_END); + (*size) = ftell(fp); + fseek(fp, offset, SEEK_SET); + char *data = (char*)malloc(*size); + fread(data, *size, sizeof(char), fp); + fseek(fp, offset, SEEK_SET); + return(data); } + static int32_t make_id(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { - return (a << 24) | (b << 16) | (c << 8) | d; + return (a << 24) | (b << 16) | (c << 8) | d; } + static int get_type(int magic) { - /*fprintf(audio_log, "magic = %x\n", magic);*/ - if (magic == make_id('F','O','R','M')) - return FORM; - if (magic == make_id('M','O','D',' ')) - return MOD; - if (magic == make_id('O','G','G','V')) - return OGGV; - return -1; + /*fprintf(audio_log, "magic = %x\n", magic);*/ + if (magic == make_id('F','O','R','M')) + return FORM; + if (magic == make_id('M','O','D',' ')) + return MOD; + if (magic == make_id('O','G','G','V')) + return OGGV; + return -1; } + static float limit(float mn, float mx, float v) { - if(vmx) return mx; - return v; + if (vmx) return mx; + return v; } @@ -254,28 +257,28 @@ limit(float mn, float mx, float v) static resampler_t* resampler_init(int sample_rate_input) { - resampler_t *rsmp = (resampler_t*)calloc(sizeof(resampler_t), 1); - int error; - rsmp->src_state = src_new(SRC_SINC_FASTEST, 2, &error); - rsmp->input = (float*)calloc(frotz_audio.buffer_size, sizeof(float)*2); - rsmp->output = (float*)calloc(frotz_audio.buffer_size, sizeof(float)*2); - rsmp->scratch = (float*)calloc(frotz_audio.buffer_size, sizeof(float)*2); - rsmp->src_data.src_ratio = frotz_audio.sample_rate*1.0f/sample_rate_input; - rsmp->src_data.input_frames = 0; - rsmp->src_data.output_frames = frotz_audio.buffer_size; - rsmp->src_data.data_in = rsmp->input; - rsmp->src_data.data_out = rsmp->output; - rsmp->src_data.end_of_input = 0; - - return rsmp; + resampler_t *rsmp = (resampler_t*)calloc(sizeof(resampler_t), 1); + int error; + rsmp->src_state = src_new(SRC_SINC_FASTEST, 2, &error); + rsmp->input = (float*)calloc(frotz_audio.buffer_size, sizeof(float)*2); + rsmp->output = (float*)calloc(frotz_audio.buffer_size, sizeof(float)*2); + rsmp->scratch = (float*)calloc(frotz_audio.buffer_size, sizeof(float)*2); + rsmp->src_data.src_ratio = frotz_audio.sample_rate*1.0f/sample_rate_input; + rsmp->src_data.input_frames = 0; + rsmp->src_data.output_frames = frotz_audio.buffer_size; + rsmp->src_data.data_in = rsmp->input; + rsmp->src_data.data_out = rsmp->output; + rsmp->src_data.end_of_input = 0; + + return rsmp; } static void resampler_cleanup(resampler_t *rsmp) { - src_delete(rsmp->src_state); - free(rsmp->input); - free(rsmp->output); - free(rsmp->scratch); + src_delete(rsmp->src_state); + free(rsmp->input); + free(rsmp->output); + free(rsmp->scratch); } @@ -283,43 +286,45 @@ resampler_cleanup(resampler_t *rsmp) static int resampler_step(resampler_t *rsmp, float *block) { - /*Always stereo*/ - const int channels = 2; - const int smps = frotz_audio.buffer_size; - if(block) { - assert(rsmp->src_data.input_frames == 0); - memcpy(rsmp->input, block, channels*smps*sizeof(float)); - rsmp->src_data.data_in = rsmp->input; - rsmp->src_data.input_frames = smps; - } - int err = src_process(rsmp->src_state, &rsmp->src_data); - assert(err == 0); - - int u_in = rsmp->src_data.input_frames_used; - rsmp->src_data.data_in += 2*u_in; - rsmp->src_data.input_frames -= u_in; - /* - * If input buffer is empty, reset data_in pointer just in case - * the output buffer is also full. - */ - if(rsmp->src_data.input_frames == 0) - rsmp->src_data.data_in = rsmp->input; - int g_out = rsmp->src_data.output_frames_gen; - rsmp->src_data.data_out += 2*g_out; - rsmp->src_data.output_frames -= g_out; - - if(rsmp->src_data.output_frames == 0) - return 0; - return 1; + /*Always stereo*/ + const int channels = 2; + const int smps = frotz_audio.buffer_size; + if (block) { + assert(rsmp->src_data.input_frames == 0); + memcpy(rsmp->input, block, channels*smps*sizeof(float)); + rsmp->src_data.data_in = rsmp->input; + rsmp->src_data.input_frames = smps; + } + int err = src_process(rsmp->src_state, &rsmp->src_data); + assert(err == 0); + + int u_in = rsmp->src_data.input_frames_used; + rsmp->src_data.data_in += 2*u_in; + rsmp->src_data.input_frames -= u_in; + /* + * If input buffer is empty, reset data_in pointer just in case + * the output buffer is also full. + */ + if (rsmp->src_data.input_frames == 0) + rsmp->src_data.data_in = rsmp->input; + int g_out = rsmp->src_data.output_frames_gen; + rsmp->src_data.data_out += 2*g_out; + rsmp->src_data.output_frames -= g_out; + + if (rsmp->src_data.output_frames == 0) + return 0; + return 1; } + static void resampler_consume(resampler_t *rsmp) { - rsmp->src_data.data_out = rsmp->output; - rsmp->src_data.output_frames = frotz_audio.buffer_size; + rsmp->src_data.data_out = rsmp->output; + rsmp->src_data.output_frames = frotz_audio.buffer_size; } + /********************************************************************** * MOD * * * @@ -333,18 +338,18 @@ resampler_consume(resampler_t *rsmp) static int process_mod(sound_stream_t *self_, float *outl, float *outr, unsigned samples) { - sound_stream_mod_t *self = (sound_stream_mod_t*)self_; + sound_stream_mod_t *self = (sound_stream_mod_t*)self_; - int n = ModPlug_Read(self->mod, self->shortbuffer, samples*4) / 4; - const float scale = (1.0f/32768.0f);/*volfactor;*/ - int i; - for(i=0; ishortbuffer[i*2+0]; - outr[i] += scale*self->shortbuffer[i*2+1]; - } + int n = ModPlug_Read(self->mod, self->shortbuffer, samples*4) / 4; + const float scale = (1.0f/32768.0f);/*volfactor;*/ + int i; + for (i=0; ishortbuffer[i*2+0]; + outr[i] += scale*self->shortbuffer[i*2+1]; + } - if(n <= 0) - return 0; + if (n <= 0) + return 0; return 1; } @@ -352,54 +357,55 @@ process_mod(sound_stream_t *self_, float *outl, float *outr, unsigned samples) static void cleanup_mod(sound_stream_t *s) { - sound_stream_mod_t *self = (sound_stream_mod_t*)s; - ModPlug_Unload(self->mod); - free(self->shortbuffer); - free(self->filedata); + sound_stream_mod_t *self = (sound_stream_mod_t*)s; + ModPlug_Unload(self->mod); + free(self->shortbuffer); + free(self->filedata); } + /*file, data start, id, volume*/ static sound_stream_t * load_mod(FILE *fp, long startpos, int id, float volume) { - sound_stream_mod_t *stream = (sound_stream_mod_t*)calloc(sizeof(sound_stream_mod_t), 1); - long size; - long filestart = ftell(fp); - fseek(fp, startpos, SEEK_SET); + sound_stream_mod_t *stream = (sound_stream_mod_t*)calloc(sizeof(sound_stream_mod_t), 1); + long size; + long filestart = ftell(fp); + fseek(fp, startpos, SEEK_SET); - stream->id = id; - stream->sound_type = MOD; - stream->process = process_mod; - stream->cleanup = cleanup_mod; + stream->id = id; + stream->sound_type = MOD; + stream->process = process_mod; + stream->cleanup = cleanup_mod; - ModPlug_GetSettings(&stream->settings); + ModPlug_GetSettings(&stream->settings); - /* Note: All "Basic Settings" must be set before ModPlug_Load. */ - stream->settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; /* RESAMP */ - stream->settings.mChannels = 2; - stream->settings.mBits = 16; - stream->settings.mFrequency = frotz_audio.sample_rate; - stream->settings.mStereoSeparation = 128; - stream->settings.mMaxMixChannels = 256; + /* Note: All "Basic Settings" must be set before ModPlug_Load. */ + stream->settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; /* RESAMP */ + stream->settings.mChannels = 2; + stream->settings.mBits = 16; + stream->settings.mFrequency = frotz_audio.sample_rate; + stream->settings.mStereoSeparation = 128; + stream->settings.mMaxMixChannels = 256; - /* insert more setting changes here */ - ModPlug_SetSettings(&stream->settings); + /* insert more setting changes here */ + ModPlug_SetSettings(&stream->settings); - /* remember to free() filedata later */ - stream->filedata = getfiledata(fp, &size); + /* remember to free() filedata later */ + stream->filedata = getfiledata(fp, &size); - stream->mod = ModPlug_Load(stream->filedata, size); - fseek(fp, filestart, SEEK_SET); - if (!stream->mod) { - fprintf(stderr, "Unable to load MOD chunk.\n\r"); - return 0; - } + stream->mod = ModPlug_Load(stream->filedata, size); + fseek(fp, filestart, SEEK_SET); + if (!stream->mod) { + fprintf(stderr, "Unable to load MOD chunk.\n\r"); + return 0; + } - ModPlug_SetMasterVolume(stream->mod, volume * 256);/*powf(2.0f, 8.0f));*/ + ModPlug_SetMasterVolume(stream->mod, volume * 256);/*powf(2.0f, 8.0f));*/ - stream->shortbuffer = (int16_t*)calloc(frotz_audio.buffer_size, sizeof(short) * 2); + stream->shortbuffer = (int16_t*)calloc(frotz_audio.buffer_size, sizeof(short) * 2); - return (sound_stream_t*)stream; + return (sound_stream_t*)stream; } /********************************************************************** @@ -420,181 +426,186 @@ load_mod(FILE *fp, long startpos, int id, float volume) static int process_aiff(sound_stream_t *self_, float *outl, float *outr, unsigned samples) { - sound_stream_aiff_t *self = (sound_stream_aiff_t*)self_; - - int needs_data = resampler_step(self->rsmp, 0); - int i; - unsigned remaining_samples = samples; - - while(needs_data) { - int inf = sf_readf_float(self->sndfile, - self->floatbuffer, - remaining_samples); - if(self->sf_info.channels == 1) { - for(i=0; irsmp->scratch[2*i+0+2*(samples-remaining_samples)] = - self->floatbuffer[i]; - self->rsmp->scratch[2*i+1+2*(samples-remaining_samples)] = - self->floatbuffer[i]; - } - } else if(self->sf_info.channels == 2) { - for(i=0; irsmp->scratch[2*i+0+2*(samples-remaining_samples)] = - self->floatbuffer[2*i+0]; - self->rsmp->scratch[2*i+1+2*(samples-remaining_samples)] = - self->floatbuffer[2*i+1]; - } - } - /* - * If the read function didn't fill the scratch buffer, see if - * there are more repeats and if so, continue filling the scratch - * buffer, a repeat value of 255 means repeat forever - */ - if(inf < remaining_samples) { - if(self->repeats<255) - self->repeats--; - if(self->repeats > 0){ - /* - * Repeating... Seek back to the beginning of the sound - * and allow the read to get enough samples to fill the - * scratch buffer, and continue with the while loop - */ - sf_seek(self->sndfile,0, SEEK_SET); - if( inf == remaining_samples) - remaining_samples = samples; - else - remaining_samples = remaining_samples-inf; - continue; - } else if(inf <= 0) { + sound_stream_aiff_t *self = (sound_stream_aiff_t*)self_; + + int needs_data = resampler_step(self->rsmp, 0); + int i; + unsigned remaining_samples = samples; + + while(needs_data) { + int inf = sf_readf_float(self->sndfile, + self->floatbuffer, remaining_samples); + if (self->sf_info.channels == 1) { + for (i=0; irsmp->scratch[2*i+0+2*(samples-remaining_samples)] = + self->floatbuffer[i]; + self->rsmp->scratch[2*i+1+2*(samples-remaining_samples)] = + self->floatbuffer[i]; + } + } else if (self->sf_info.channels == 2) { + for (i=0; irsmp->scratch[2*i+0+2*(samples-remaining_samples)] = + self->floatbuffer[2*i+0]; + self->rsmp->scratch[2*i+1+2*(samples-remaining_samples)] = + self->floatbuffer[2*i+1]; + } + } /* - * No repeats and no data left in the sound file, - * return 0 to tell the next level up that the sound - * is done + * If the read function didn't fill the scratch buffer, see if + * there are more repeats and if so, continue filling the scratch + * buffer, a repeat value of 255 means repeat forever */ - - return 0; - } else { - /* - * No repeats but there was data read, set things back - * up so that the maximum buffer size can be read, but - * fall through to make sure the data is resampled - */ - remaining_samples = samples; - } + if (inf < remaining_samples) { + if (self->repeats<255) + self->repeats--; + if (self->repeats > 0){ + /* + * Repeating... Seek back to the beginning of the sound + * and allow the read to get enough samples to fill the + * scratch buffer, and continue with the while loop + */ + sf_seek(self->sndfile,0, SEEK_SET); + if ( inf == remaining_samples) + remaining_samples = samples; + else + remaining_samples = remaining_samples - inf; + continue; + } else if (inf <= 0) { + /* + * No repeats and no data left in the sound file, + * return 0 to tell the next level up that the sound + * is done + */ + return 0; + } else { + /* + * No repeats but there was data read, set things back + * up so that the maximum buffer size can be read, but + * fall through to make sure the data is resampled + */ + remaining_samples = samples; + } + } + needs_data = resampler_step(self->rsmp, self->rsmp->scratch); + } + resampler_consume(self->rsmp); + + for (i=0; i<(int)samples; ++i) { + outl[i] += self->rsmp->output[2*i+0]*self->volume; + outr[i] += self->rsmp->output[2*i+1]*self->volume; } - needs_data = resampler_step(self->rsmp, self->rsmp->scratch); - } - resampler_consume(self->rsmp); - for(i=0; i<(int)samples; ++i) { - outl[i] += self->rsmp->output[2*i+0]*self->volume; - outr[i] += self->rsmp->output[2*i+1]*self->volume; - } - - return 1; + return 1; } + static void cleanup_aiff(sound_stream_t *s) { - sound_stream_aiff_t *self = (sound_stream_aiff_t*)s; + sound_stream_aiff_t *self = (sound_stream_aiff_t*)s; - /*Cleanup frame*/ - resampler_cleanup(self->rsmp); - free(self->rsmp); - sf_close(self->sndfile); - free(self->floatbuffer); + /* Cleanup frame */ + resampler_cleanup(self->rsmp); + free(self->rsmp); + sf_close(self->sndfile); + free(self->floatbuffer); } + static sf_count_t mem_snd_read(void *ptr_, sf_count_t size, void* datasource) { - uint8_t *ptr = (uint8_t*)ptr_; - file_reader_t *fr = (file_reader_t *)datasource; - size_t to_read = size; - size_t read_total = 0; - ssize_t did_read = 0; - while(to_read > 0) { - did_read = pread(fileno(fr->file), ptr, size, fr->pos+fr->base_offset); - if(did_read < 0) - return did_read; - else if(did_read == 0) - return read_total; - read_total += did_read; - fr->pos += did_read; - ptr += did_read; - to_read -= did_read; - } - return read_total; + uint8_t *ptr = (uint8_t*)ptr_; + file_reader_t *fr = (file_reader_t *)datasource; + size_t to_read = size; + size_t read_total = 0; + ssize_t did_read = 0; + while (to_read > 0) { + did_read = pread(fileno(fr->file), ptr, size, fr->pos+fr->base_offset); + if (did_read < 0) + return did_read; + else if (did_read == 0) + return read_total; + read_total += did_read; + fr->pos += did_read; + ptr += did_read; + to_read -= did_read; + } + return read_total; } + static sf_count_t mem_snd_seek(sf_count_t offset, int whence, void *datasource) { - file_reader_t *fr = (file_reader_t *)datasource; - int64_t pos = 0; - if(whence == SEEK_SET) - pos = offset; - if(whence == SEEK_CUR) - pos += offset; - if(whence == SEEK_END) - pos = fr->len-offset; - if(pos >= (int64_t)fr->len) - pos = fr->len-1; - if(pos < 0) - pos = 0; - fr->pos = pos; + file_reader_t *fr = (file_reader_t *)datasource; + int64_t pos = 0; + if (whence == SEEK_SET) + pos = offset; + if (whence == SEEK_CUR) + pos += offset; + if (whence == SEEK_END) + pos = fr->len-offset; + if (pos >= (int64_t)fr->len) + pos = fr->len-1; + if (pos < 0) + pos = 0; + fr->pos = pos; - return 0; + return 0; } static long mem_tell(void *datasource) { - file_reader_t *fr = (file_reader_t*)datasource; - return fr->pos; + file_reader_t *fr = (file_reader_t*)datasource; + return fr->pos; } + static sf_count_t mem_get_filelen(void *datasource) { - file_reader_t *fr = (file_reader_t*)datasource; - return fr->len; + file_reader_t *fr = (file_reader_t*)datasource; + return fr->len; } + static sound_stream_t * load_aiff(FILE *fp, long startpos, long length, int id, float volume, int repeats) { - sound_stream_aiff_t *aiff = - (sound_stream_aiff_t*)calloc(sizeof(sound_stream_aiff_t), 1); - aiff->sound_type = FORM; - aiff->id = id; - aiff->process = process_aiff; - aiff->cleanup = cleanup_aiff; - aiff->repeats = repeats; + sound_stream_aiff_t *aiff = + (sound_stream_aiff_t*)calloc(sizeof(sound_stream_aiff_t), 1); + aiff->sound_type = FORM; + aiff->id = id; + aiff->process = process_aiff; + aiff->cleanup = cleanup_aiff; + aiff->repeats = repeats; - aiff->volume = volume; - aiff->sf_info.format = 0; + aiff->volume = volume; + aiff->sf_info.format = 0; - fseek(fp, startpos, SEEK_SET); - aiff->freader.file = fp; - aiff->freader.pos = 0; - aiff->freader.len = length; - aiff->freader.base_offset = startpos; + fseek(fp, startpos, SEEK_SET); + aiff->freader.file = fp; + aiff->freader.pos = 0; + aiff->freader.len = length; + aiff->freader.base_offset = startpos; - SF_VIRTUAL_IO mem_cb = { - .seek = mem_snd_seek, - .read = mem_snd_read, - .tell = (sf_vio_tell)mem_tell, - .get_filelen = mem_get_filelen, - .write = NULL - }; + SF_VIRTUAL_IO mem_cb = { + .seek = mem_snd_seek, + .read = mem_snd_read, + .tell = (sf_vio_tell)mem_tell, + .get_filelen = mem_get_filelen, + .write = NULL + }; - aiff->sndfile = sf_open_virtual(&mem_cb, SFM_READ, &aiff->sf_info, &aiff->freader); - aiff->rsmp = resampler_init(aiff->sf_info.samplerate); + aiff->sndfile = sf_open_virtual(&mem_cb, SFM_READ, + &aiff->sf_info, &aiff->freader); + aiff->rsmp = resampler_init(aiff->sf_info.samplerate); - aiff->floatbuffer = (float*)malloc(frotz_audio.buffer_size * aiff->sf_info.channels * sizeof(float)); + aiff->floatbuffer = (float*)malloc(frotz_audio.buffer_size * + aiff->sf_info.channels * sizeof(float)); - return (sound_stream_t*) aiff; + return (sound_stream_t*) aiff; } @@ -625,197 +636,206 @@ sound_stop_id_real(sound_engine_t *e, int id); static void process_engine(sound_engine_t *e) { - int i; - /*Handle event*/ - if(ux_sem_trywait(&e->ev_pending) == 0) { - if(e->event.type == EVENT_START_STREAM) - sound_enqueue_real(e,e->event.e); - else if(e->event.type == EVENT_STOP_STREAM) - sound_stop_id_real(e,e->event.i); - ux_sem_post(&e->ev_free); - } - - /*Start out with an empty buffer*/ - memset(e->outl, 0, sizeof(float)*e->buffer_size); - memset(e->outr, 0, sizeof(float)*e->buffer_size); - - for(i=0; i<8; ++i) { - sound_state_t *state = &e->voices[i]; - - /*Only process active voices*/ - if(!state->active) - continue; - - sound_stream_t *sound = e->streams[i]; - - if(sound) { - int ret = sound->process(sound, e->outl, e->outr, e->buffer_size); - if(ret == 0) { - /*fprintf(audio_log, "stream #%d is complete\n", i);*/ - state->active = false; - sound->cleanup(sound); - free(sound); - e->streams[i] = NULL; - ux_sem_post(&sound_done); - } - } - } + int i; + /* Handle event */ + if (ux_sem_trywait(&e->ev_pending) == 0) { + if (e->event.type == EVENT_START_STREAM) + sound_enqueue_real(e,e->event.e); + else if (e->event.type == EVENT_STOP_STREAM) + sound_stop_id_real(e,e->event.i); + ux_sem_post(&e->ev_free); + } + + /* Start out with an empty buffer */ + memset(e->outl, 0, sizeof(float)*e->buffer_size); + memset(e->outr, 0, sizeof(float)*e->buffer_size); + + for (i=0; i<8; ++i) { + sound_state_t *state = &e->voices[i]; + + /* Only process active voices */ + if (!state->active) + continue; + + sound_stream_t *sound = e->streams[i]; + + if (sound) { + int ret = sound->process(sound, e->outl, e->outr, e->buffer_size); + if (ret == 0) { + /* fprintf(audio_log, "stream #%d is complete\n", i); */ + state->active = false; + sound->cleanup(sound); + free(sound); + e->streams[i] = NULL; + ux_sem_post(&sound_done); + } + } + } } + static void* audio_loop(void*v) { - (void)v; - size_t outsize = frotz_audio.buffer_size*2*sizeof(int16_t); - int16_t *buf = (int16_t*)calloc(outsize,1); - int i; - ao_device *device; - ao_sample_format format; - ao_initialize(); - int default_driver = ao_default_driver_id(); - - memset(&format, 0, sizeof(ao_sample_format)); - - format.byte_format = AO_FMT_NATIVE; - format.bits = 16; - format.channels = 2; - format.rate = 48000.0f; - device = ao_open_live(default_driver, &format, NULL); - - while(1) { - process_engine(&frotz_audio); - - const float mul = (32768.0f); - for(i=0; i<(int)frotz_audio.buffer_size; ++i) { - buf[2*i+0] = limit(-32764,32767,mul*0.8*frotz_audio.outl[i]); - buf[2*i+1] = limit(-32764,32767,mul*0.8*frotz_audio.outr[i]); - } - ao_play(device, (char*)buf, outsize); - } - return 0; + (void) v; + size_t outsize = frotz_audio.buffer_size*2*sizeof(int16_t); + int16_t *buf = (int16_t*)calloc(outsize,1); + int i; + ao_device *device; + ao_sample_format format; + ao_initialize(); + int default_driver = ao_default_driver_id(); + + memset(&format, 0, sizeof(ao_sample_format)); + + format.byte_format = AO_FMT_NATIVE; + format.bits = 16; + format.channels = 2; + format.rate = 48000.0f; + device = ao_open_live(default_driver, &format, NULL); + + while (1) { + process_engine(&frotz_audio); + + const float mul = (32768.0f); + for (i=0; i<(int)frotz_audio.buffer_size; ++i) { + buf[2*i+0] = limit(-32764,32767,mul*0.8*frotz_audio.outl[i]); + buf[2*i+1] = limit(-32764,32767,mul*0.8*frotz_audio.outr[i]); + } + ao_play(device, (char*)buf, outsize); + } + return 0; } static void sound_halt_aiff(void) { - int i; - for(i=0; isound_type == FORM) { - /*fprintf(audio_log, "killing aiff stream #%d\n", i);*/ - sound_stream_t *s = frotz_audio.streams[i]; - frotz_audio.streams[i] = 0; - s->cleanup(s); - free(s); - } - } + int i; + for (i=0; isound_type == FORM) { + /* fprintf(audio_log, "killing aiff stream #%d\n", i); */ + sound_stream_t *s = frotz_audio.streams[i]; + frotz_audio.streams[i] = 0; + s->cleanup(s); + free(s); + } + } } + static void sound_halt_mod(void) { - int i; - for(i=0; isound_type == MOD) { - /*fprintf(audio_log, "killing mod stream #%d\n", i);*/ - sound_stream_t *s = frotz_audio.streams[i]; - frotz_audio.streams[i] = 0; - s->cleanup(s); - free(s); - } - } + int i; + for (i=0; isound_type == MOD) { + /* fprintf(audio_log, "killing mod stream #%d\n", i); */ + sound_stream_t *s = frotz_audio.streams[i]; + frotz_audio.streams[i] = 0; + s->cleanup(s); + free(s); + } + } } + static void sound_halt_ogg(void) { - int i; - for(i=0; isound_type == OGGV) { - /*fprintf(audio_log, "killing ogg stream #%d\n", i);*/ - sound_stream_t *s = frotz_audio.streams[i]; - frotz_audio.streams[i] = 0; - s->cleanup(s); - free(s); - } - } + int i; + for(i=0; isound_type == OGGV) { + /* fprintf(audio_log, "killing ogg stream #%d\n", i); */ + sound_stream_t *s = frotz_audio.streams[i]; + frotz_audio.streams[i] = 0; + s->cleanup(s); + free(s); + } + } } + static sound_stream_t *load_mod(FILE *fp, long startpos, int id, float volume); static sound_stream_t *load_aiff(FILE *fp, long startpos, long length, int id, float volume, int repeats); + static void sound_stop_id(int id) { - ux_sem_wait(&frotz_audio.ev_free); - frotz_audio.event.type = EVENT_STOP_STREAM; - frotz_audio.event.i = id; - ux_sem_post(&frotz_audio.ev_pending); + ux_sem_wait(&frotz_audio.ev_free); + frotz_audio.event.type = EVENT_STOP_STREAM; + frotz_audio.event.i = id; + ux_sem_post(&frotz_audio.ev_pending); } + static void sound_stop_id_real(sound_engine_t *e, int id) { - int i; - for(i=0; istreams[i]; - if(s && s->id == id) { - /*fprintf(audio_log, "killing stream #%d\n", i);*/ - e->streams[i] = 0; - s->cleanup(s); - free(s); - } - } + int i; + for (i=0; istreams[i]; + if (s && s->id == id) { + /*fprintf(audio_log, "killing stream #%d\n", i);*/ + e->streams[i] = 0; + s->cleanup(s); + free(s); + } + } } + static void sound_enqueue(sound_stream_t *s) { - ux_sem_wait(&frotz_audio.ev_free); - frotz_audio.event.type = EVENT_START_STREAM; - frotz_audio.event.e = s; - ux_sem_post(&frotz_audio.ev_pending); + ux_sem_wait(&frotz_audio.ev_free); + frotz_audio.event.type = EVENT_START_STREAM; + frotz_audio.event.e = s; + ux_sem_post(&frotz_audio.ev_pending); } + static void sound_enqueue_real(sound_engine_t *e, sound_stream_t *s) { - assert(e); - assert(s); - int i; - - if(s->sound_type == FORM) { - sound_halt_aiff(); - } else if(s->sound_type == MOD) { - sound_halt_mod(); - sound_halt_ogg(); - } else if(s->sound_type == OGGV) { - sound_halt_mod(); - sound_halt_ogg(); - } - - for(i=0; istreams[i]) /*only use free voices*/ - continue; - /*fprintf(audio_log, "Enqueue %p to %d\n", s, i);*/ - e->streams[i] = s; - e->voices[i].active = true; - e->voices[i].src = 0; - e->voices[i].pos = 0; - e->voices[i].repid = 0; - break; - } + assert(e); + assert(s); + int i; + + if (s->sound_type == FORM) { + sound_halt_aiff(); + } else if (s->sound_type == MOD) { + sound_halt_mod(); + sound_halt_ogg(); + } else if (s->sound_type == OGGV) { + sound_halt_mod(); + sound_halt_ogg(); + } + + for (i=0; istreams[i]) /*only use free voices*/ + continue; + /* fprintf(audio_log, "Enqueue %p to %d\n", s, i);*/ + e->streams[i] = s; + e->voices[i].active = true; + e->voices[i].src = 0; + e->voices[i].pos = 0; + e->voices[i].repid = 0; + break; + } } + static float volume_factor(int vol) { - static float lut[8] = {0.0078125f, 0.015625f, 0.03125f, 0.0625f, 0.125f, 0.25f, 0.5f, 1.0f}; + static float lut[8] = {0.0078125f, 0.015625f, 0.03125f, 0.0625f, 0.125f, 0.25f, 0.5f, 1.0f}; - if(vol < 1) vol = 1; - if(vol > 8) vol = 8; - return lut[vol-1]; - /*return powf(2, vol - 8);*/ + if (vol < 1) vol = 1; + if (vol > 8) vol = 8; + return lut[vol-1]; + /* return powf(2, vol - 8); */ } @@ -827,41 +847,42 @@ volume_factor(int vol) void os_init_sound(void) { - int i; - int err; - static pthread_attr_t attr; - - if (!f_setup.sound_flag) return; - - /*Initialize sound engine*/ - /*audio_log = fopen("audio_log.txt", "w");*/ - /*fprintf(audio_log, "os_init_sound...\n");*/ - frotz_audio.buffer_size = 1024; - frotz_audio.sample_rate = 48000; - frotz_audio.outl = (float*)calloc(frotz_audio.buffer_size, sizeof(float)); - frotz_audio.outr = (float*)calloc(frotz_audio.buffer_size, sizeof(float)); - - for(i=0; ichunks[resource.chunknum].type); - - if (type == FORM) { - s = load_aiff(blorb_fp, - resource.data.startpos, - resource.length, - number, - vol, - repeats); - } else if (type == MOD) { - s = load_mod(blorb_fp, resource.data.startpos, number, vol); - } else if (type == OGGV) { - s = load_aiff(blorb_fp, - resource.data.startpos, - resource.length, - number, - vol, - repeats); - s->sound_type = OGGV; - } + (void) eos; + /* fprintf(audio_log, "os_start_sample(%d,%d,%d,%d)...\n",number,volume,repeats, eos); */ + /* fflush(audio_log); */ + extern bb_map_t *blorb_map; + extern FILE *blorb_fp; + + bb_result_t resource; + int type; + const float vol = volume_factor(volume); + sound_stream_t *s = 0; + + if (!f_setup.sound_flag) return; + + /* Load resource from BLORB data */ + if (blorb_map == NULL) return; + + if (bb_err_None != bb_load_resource(blorb_map, bb_method_FilePos, &resource, bb_ID_Snd, number)) + return; + + type = get_type(blorb_map->chunks[resource.chunknum].type); + + if (type == FORM) { + s = load_aiff(blorb_fp, + resource.data.startpos, + resource.length, + number, + vol, + repeats); + } else if (type == MOD) { + s = load_mod(blorb_fp, resource.data.startpos, number, vol); + } else if (type == OGGV) { + s = load_aiff(blorb_fp, + resource.data.startpos, + resource.length, + number, + vol, + repeats); + s->sound_type = OGGV; + } - if(s) - sound_enqueue(s); + if (s) + sound_enqueue(s); } void os_beep(int bv) { - (void) bv; - /*Currently implemented as a simple terminal bell*/ - /*To implement generate a high frequency beep for bv=1,*/ - /*low frequency for bv=2*/ - /*fprintf(audio_log, "os_beep(%d)...\n", bv);*/ - beep(); + (void) bv; + /* Currently implemented as a simple terminal bell */ + /* To implement generate a high frequency beep for bv=1, */ + /* low frequency for bv=2 */ + /* fprintf(audio_log, "os_beep(%d)...\n", bv); */ + beep(); } + + void os_prepare_sample(int id) { - (void) id; - /*Currently not implemented*/ - /*fprintf(audio_log, "os_prepare_sample(%d)...\n", id);*/ + (void) id; + /* Currently not implemented */ + /* fprintf(audio_log, "os_prepare_sample(%d)...\n", id); */ } + void os_stop_sample(int id) { - /*fprintf(audio_log, "os_stop_sample(%d)...\n", id);*/ - if (!f_setup.sound_flag) return; - sound_stop_id(id); + /* fprintf(audio_log, "os_stop_sample(%d)...\n", id); */ + if (!f_setup.sound_flag) return; + sound_stop_id(id); } void os_finish_with_sample(int id) { - /*fprintf(audio_log, "os_finish_with_sample(%d)...\n", id);*/ - os_stop_sample(id); + /* fprintf(audio_log, "os_finish_with_sample(%d)...\n", id); */ + os_stop_sample(id); } #endif /* NO_SOUND */