home *** CD-ROM | disk | FTP | other *** search
Wrap
#include <stdio.h> #include <stdlib.h> #include <string.h> // oslib #include "os.h" #include "osmodule.h" #include "OS:h.sound" // #include "soundcode.h" static int sound_claimed = 0; static int *sound_rma = NULL; static int sound_written = 0; static int sound_previoussamplerate; static soundcode_memory *sound_parameters; static os_dynamic_area_no sound_area = 0; /* int main(int argc, char *argv[]) { FILE *fh; int total, read, freespace, used, played, channels; short buffer[20000]; fh = fopen("ADFS::HardDisc4.$.Program.PlayModule.BillyJoel3", "rb"); channels = 2; if (soundcode_play(44100, channels) < 0) return 0; total = 0x7f000000; do { // get free space soundcode_readposition(&played, &freespace); if (freespace > 1000) { // don't bother if there's less than 1000 // don't read more than the buffer can hold... if (freespace > 20000/channels) freespace = 20000/channels; // read the data read = fread(buffer, 2*channels, freespace, fh); // if we got less than we wanted, we're at the end of the file if (read < freespace) // fill the buffer and read the total no. of samples we've used soundcode_fill(buffer, read, &used, &total); else soundcode_fill(buffer, read, &used, NULL); } } while (played < total); soundcode_stop(); return 0; } */ // soundcode_stop stop playback void soundcode_stop() { void *oldcode, *oldworkspace; if ((!sound_rma) || (!sound_claimed)) return; sound_claimed = 0; // read current handler xsound_linear_handler(0, NULL, NULL, &oldcode, &oldworkspace); if ((oldcode == sound_parameters->address) && (oldworkspace == sound_parameters->arg)) { xsound_linear_handler(1, NULL, NULL, NULL, NULL); xsoundsamplerate_select(sound_previoussamplerate, NULL, NULL); } // release memory xosmodule_free((byte *)sound_rma); xosdynamicarea_delete(sound_area); } // soundcode_play start playback // returns buffersize (in 16 bit samples/channel) for OK or -1 for error // on entry // freq playback frequency // chans no. of channels to play (1 or 2) int soundcode_play(int freq, int chans) { int rateindex, i, nsr, prevrate, sr, rate, buffersize; short *bufferstart; if (freq < 4000 || freq > 50000 || chans < 1 || chans > 2) return -1; if (sound_claimed) return -1; // make sure 16 bit sound is supported if (xsoundsamplerate_read_count(&nsr)) return -1; // find the best playback-frequency rateindex = -1; xsoundsamplerate_lookup(1, &prevrate); prevrate = prevrate >> 10; for (sr = 2; sr <= nsr; sr++) { xsoundsamplerate_lookup(sr, &rate); rate = rate >> 10; if ((rateindex == -1) && (prevrate < freq) && (rate >= freq)) rateindex = sr; prevrate = rate; } if (rateindex == -1) return -1; // get RMA block for buffer-fill-code sound_rma = NULL; if (xosmodule_alloc(4*SOUNDCODE_SIZE, (void **)&sound_rma)) return -1; // copy buffer-fill-code for (i = 0; i < SOUNDCODE_SIZE; i++) sound_rma[i] = soundcode[i]; sound_rma[SOUNDCODE_FILLCODE] += (int)sound_rma; sound_parameters = (soundcode_memory *)&sound_rma[SOUNDCODE_PARAMETERS]; // get ~2 seconds buffer buffersize = 2*2*chans*freq & ~4095; if (xosdynamicarea_create((os_dynamic_area_no)-1, buffersize, (byte *)-1, 128, buffersize, NULL, NULL, "Sound buffer", &sound_area, (byte **)&bufferstart, NULL)) { xosmodule_free((byte *)sound_rma); return -1; } buffersize /= 2; // convert from bytes to samples // init the parameter-block passed to the buffer-fill-code sound_parameters->startaddress = bufferstart; sound_parameters->buffersize = buffersize; sound_parameters->readpos = sound_parameters->writepos = 0; sound_parameters->channels = chans; sound_parameters->flags = 0; // select samplerate xsoundsamplerate_read_current(&sound_previoussamplerate, NULL); xsoundsamplerate_select(rateindex, NULL, NULL); sound_parameters->address = (void *)sound_rma[SOUNDCODE_FILLCODE]; sound_parameters->arg = sound_parameters; xsound_linear_handler(1, sound_parameters->address, sound_parameters->arg, NULL, NULL); sound_claimed = 1; sound_written = 0; return buffersize/chans; } // soundcode_fill fill the sample-buffer // returns 0 for OK or -1 for error // on entry // buffer pointer to samples // samples no. of samples/channel in the buffer // on exit // used no. of samples/channel read from the buffer // given total no. of samples/channel written since start int soundcode_fill(short *buffer, int samples, int *used, int *given) { int n, chns, firstpart, secondpart; if ((!sound_rma) || (!sound_claimed)) return -1; *used = 0; if (given) *given = sound_written; if (samples <= 0) return 0; chns = sound_parameters->channels; // no. of samples/channel waiting to be filled n = sound_parameters->readpos - sound_parameters->writepos; if (n <= 0) n += sound_parameters->buffersize; n = n/chns; if (chns == 2) n &= ~1; if (n < 4) { // don't bother *used = 0; return 0; } n -= 2; // never fill completely if (n > samples) n = samples; firstpart = (sound_parameters->buffersize - sound_parameters->writepos)/chns; if (firstpart > n) firstpart = n; memcpy(sound_parameters->startaddress + sound_parameters->writepos, buffer, 2*chns*firstpart); sound_parameters->writepos += chns*firstpart; if (sound_parameters->writepos == sound_parameters->buffersize) sound_parameters->writepos = 0; secondpart = n - firstpart; if (secondpart > 0) { memcpy(sound_parameters->startaddress, buffer + chns*firstpart, 2*chns*secondpart); sound_parameters->writepos = chns*secondpart; } *used = n; sound_written += n; if (given) *given = sound_written; return 0; } // soundcode_readposition read info about playback // returns 0 for OK or -1 for error // on exit // played no. of samples/channel played // freespace amount of free space (samples/channel) in buffer int soundcode_readposition(int *played, int *freespace) { if ((!sound_rma) || (!sound_claimed)) return -1; if (played) *played = sound_parameters->playedsamples; if (freespace) { int n; n = sound_parameters->readpos - sound_parameters->writepos; if (n <= 0) n += sound_parameters->buffersize; *freespace = n/sound_parameters->channels; } return 0; } // soundcode_control read/write buffer/flags // on entry // newflags new flags or -1 // bit 0 set pause playback // bit 0 clear continue playback // bit 1 set repeated playback // bit 1 clear normal playback // newreadpos new read pos or -1 // newwritepos new write pos or -1 // on exit // oldflags old flags // oldreadpos old read pos // oldwritepos old write pos // bufferstart pointer to start of buffer // buffersize size of buffer (in bytes) int soundcode_control(int newflags, int newreadpos, int newwritepos, int *oldflags, int *oldreadpos, int *oldwritepos, short **bufferstart, int *buffersize) { if ((!sound_rma) || (!sound_claimed)) return -1; if (oldflags) *oldflags = sound_parameters->flags; if (oldreadpos) *oldreadpos = sound_parameters->readpos; if (oldwritepos) *oldwritepos = sound_parameters->writepos; if (bufferstart) *bufferstart = sound_parameters->startaddress; if (buffersize) *buffersize = sound_parameters->buffersize*2; if (newflags != -1) sound_parameters->flags = newflags; if (newreadpos != -1) sound_parameters->readpos = newreadpos; if (newwritepos != -1) sound_parameters->writepos = newwritepos; return 0; }