diff --git a/internal/c/parts/audio/decode/src.c b/internal/c/parts/audio/decode/src.c index 91f2d7845..ede3eac9a 100644 --- a/internal/c/parts/audio/decode/src.c +++ b/internal/c/parts/audio/decode/src.c @@ -8,25 +8,25 @@ #define DEPENDENCY_AUDIO_DECODE_WAV #ifdef QB64_BACKSLASH_FILESYSTEM - #ifdef DEPENDENCY_AUDIO_DECODE_MP3 - #include "mp3_mini\\src.c" - #endif - #ifdef DEPENDENCY_AUDIO_DECODE_WAV - #include "wav\\src.c" - #endif - #ifdef DEPENDENCY_AUDIO_DECODE_OGG - #include "ogg\\src.c" - #endif +#ifdef DEPENDENCY_AUDIO_DECODE_MP3 +#include "mp3_mini\\src.c" +#endif +#ifdef DEPENDENCY_AUDIO_DECODE_WAV +#include "wav\\src.c" +#endif +#ifdef DEPENDENCY_AUDIO_DECODE_OGG +#include "ogg\\src.c" +#endif #else - #ifdef DEPENDENCY_AUDIO_DECODE_MP3 - #include "mp3_mini/src.c" - #endif - #ifdef DEPENDENCY_AUDIO_DECODE_WAV - #include "wav/src.c" - #endif - #ifdef DEPENDENCY_AUDIO_DECODE_OGG - #include "ogg/src.c" - #endif +#ifdef DEPENDENCY_AUDIO_DECODE_MP3 +#include "mp3_mini/src.c" +#endif +#ifdef DEPENDENCY_AUDIO_DECODE_WAV +#include "wav/src.c" +#endif +#ifdef DEPENDENCY_AUDIO_DECODE_OGG +#include "ogg/src.c" +#endif #endif //forward refs: @@ -34,248 +34,248 @@ void sub__sndvol(int32 handle,float volume); void sub__sndclose(int32 handle); int32 func__sndopen(qbs* filename,qbs* requirements,int32 passed){ -sndsetup(); -if (new_error) return 0; + sndsetup(); + if (new_error) return 0; -static qbs *s1=NULL; -if (!s1) s1=qbs_new(0,0); -static qbs *req=NULL; -if (!req) req=qbs_new(0,0); -static qbs *s3=NULL; -if (!s3) s3=qbs_new(0,0); + static qbs *s1=NULL; + if (!s1) s1=qbs_new(0,0); + static qbs *req=NULL; + if (!req) req=qbs_new(0,0); + static qbs *s3=NULL; + if (!s3) s3=qbs_new(0,0); -static uint8 r[32]; -static int32 i,i2,i3; -//check requirements -memset(r,0,32); -if (passed){ -if (requirements->len){ -i=1; -qbs_set(req,qbs_ucase(requirements));//convert tmp str to perm str + static uint8 r[32]; + static int32 i,i2,i3; + //check requirements + memset(r,0,32); + if (passed){ + if (requirements->len){ + i=1; + qbs_set(req,qbs_ucase(requirements));//convert tmp str to perm str nextrequirement: -i2=func_instr(i,req,qbs_new_txt(","),1); -if (i2){ -qbs_set(s1,func_mid(req,i,i2-i,1)); -}else{ -qbs_set(s1,func_mid(req,i,req->len-i+1,1)); -} -qbs_set(s1,qbs_rtrim(qbs_ltrim(s1))); -if (qbs_equal(s1,qbs_new_txt("SYNC"))){r[0]++; goto valid;} -if (qbs_equal(s1,qbs_new_txt("VOL"))){r[1]++; goto valid;} -if (qbs_equal(s1,qbs_new_txt("PAUSE"))){r[2]++; goto valid;} -if (qbs_equal(s1,qbs_new_txt("LEN"))){r[3]++; goto valid;} -if (qbs_equal(s1,qbs_new_txt("SETPOS"))){r[4]++; goto valid;} -error(5); return 0;//invalid requirements + i2=func_instr(i,req,qbs_new_txt(","),1); + if (i2){ + qbs_set(s1,func_mid(req,i,i2-i,1)); + }else{ + qbs_set(s1,func_mid(req,i,req->len-i+1,1)); + } + qbs_set(s1,qbs_rtrim(qbs_ltrim(s1))); + if (qbs_equal(s1,qbs_new_txt("SYNC"))){r[0]++; goto valid;} + if (qbs_equal(s1,qbs_new_txt("VOL"))){r[1]++; goto valid;} + if (qbs_equal(s1,qbs_new_txt("PAUSE"))){r[2]++; goto valid;} + if (qbs_equal(s1,qbs_new_txt("LEN"))){r[3]++; goto valid;} + if (qbs_equal(s1,qbs_new_txt("SETPOS"))){r[4]++; goto valid;} + error(5); return 0;//invalid requirements valid: -if (i2){i=i2+1; goto nextrequirement;} -for (i=0;i<32;i++) if (r[i]>1){error(5); return 0;}//cannot define requirements twice -}//->len -}//passed -qbs_set(s1,qbs_add(filename,qbs_new_txt_len("\0",1)));//s1=filename+CHR$(0) + if (i2){i=i2+1; goto nextrequirement;} + for (i=0;i<32;i++) if (r[i]>1){error(5); return 0;}//cannot define requirements twice + }//->len + }//passed + qbs_set(s1,qbs_add(filename,qbs_new_txt_len("\0",1)));//s1=filename+CHR$(0) -if (!r[0]){//NOT SYNC - if (snd_stream_handle){error(5); return 0;}//stream in use -} + if (!r[0]){//NOT SYNC + if (snd_stream_handle){error(5); return 0;}//stream in use + } -//load file -if (s1->len==1) return 0;//return invalid handle if null length string -static int32 fh,result; -static int64 lof; -fh=gfs_open(s1,1,0,0); -if (fh<0) return 0; -lof=gfs_lof(fh); -static uint8* content; -content=(uint8*)malloc(lof); if (!content){gfs_close(fh); return 0;} -result=gfs_read(fh,-1,content,lof); -gfs_close(fh); -if (result<0){free(content); return 0;} + //load file + if (s1->len==1) return 0;//return invalid handle if null length string + static int32 fh,result; + static int64 lof; + fh=gfs_open(s1,1,0,0); + if (fh<0) return 0; + lof=gfs_lof(fh); + static uint8* content; + content=(uint8*)malloc(lof); if (!content){gfs_close(fh); return 0;} + result=gfs_read(fh,-1,content,lof); + gfs_close(fh); + if (result<0){free(content); return 0;} -//identify file format -static snd_sequence_struct *seq; + //identify file format + static snd_sequence_struct *seq; -//OGG? + //OGG? #ifdef DEPENDENCY_AUDIO_DECODE_OGG -if (lof>=3){ -if (content[0]==79){ if (content[1]==103){ if (content[2]==103){//"Ogg" - seq=snd_decode_ogg(content,lof); - goto got_seq; -}}} -}//3 + if (lof>=3){ + if (content[0]==79){ if (content[1]==103){ if (content[2]==103){//"Ogg" + seq=snd_decode_ogg(content,lof); + goto got_seq; + }}} + }//3 #endif -//WAV? + //WAV? #ifdef DEPENDENCY_AUDIO_DECODE_WAV -if (lof>=12){ - if ((*(uint32*)&content[8])==0x45564157){//WAVE - seq=snd_decode_wav(content,lof); - goto got_seq; - }//WAVE -} + if (lof>=12){ + if ((*(uint32*)&content[8])==0x45564157){//WAVE + seq=snd_decode_wav(content,lof); + goto got_seq; + }//WAVE + } #endif -//assume mp3! -//MP3? + //assume mp3! + //MP3? #ifdef DEPENDENCY_AUDIO_DECODE_MP3 -seq=snd_decode_mp3(content,lof); + seq=snd_decode_mp3(content,lof); #endif got_seq: -free(content); -if (seq==NULL) return 0; + free(content); + if (seq==NULL) return 0; -//convert sequence (includes sample rate conversion etc etc) + //convert sequence (includes sample rate conversion etc etc) -//just perform sample_rate fix for now... + //just perform sample_rate fix for now... -//1. 8->16bit conversion and/or edian conversion -static int32 incorrect_format; -incorrect_format=0; -if (seq->bits_per_sample!=16) incorrect_format=1; -if (seq->is_unsigned) incorrect_format=1; -//todo... if (seq->endian==???) + //1. 8->16bit conversion and/or edian conversion + static int32 incorrect_format; + incorrect_format=0; + if (seq->bits_per_sample!=16) incorrect_format=1; + if (seq->is_unsigned) incorrect_format=1; + //todo... if (seq->endian==???) -//this section does not fix the frequency, only the bits per sample -//and signed-ness of the data -if (incorrect_format){ - static int32 bps; bps=seq->bits_per_sample/8; - static int32 samples; samples=seq->data_size/bps; - static uint8 *new_data; - if (bps!=2){ - new_data=(uint8*)malloc(samples*2); - }else{ - new_data=seq->data; - } - static int32 i,v; - for (i=0;iis_unsigned){ - v=*(uint8*)(seq->data+i*1); - v=(v-128)*256; - }else{ - v=*(int8*)(seq->data+i*1); - v=v*128; - } - } - if (bps==2){ - if (seq->is_unsigned){ - v=*(uint16*)(seq->data+i*2); - v=v-32768; - }else{ - v=*(int16*)(seq->data+i*2); - } - } - //place new value into array - ((int16*)new_data)[i]=v; - }//i - if (bps!=2){free(seq->data); seq->data=new_data; seq->data_size=samples*2;} - //update seq info - seq->bits_per_sample=16; - seq->is_unsigned=0; -}//incorrect format + //this section does not fix the frequency, only the bits per sample + //and signed-ness of the data + if (incorrect_format){ + static int32 bps; bps=seq->bits_per_sample/8; + static int32 samples; samples=seq->data_size/bps; + static uint8 *new_data; + if (bps!=2){ + new_data=(uint8*)malloc(samples*2); + }else{ + new_data=seq->data; + } + static int32 i,v; + for (i=0;iis_unsigned){ + v=*(uint8*)(seq->data+i*1); + v=(v-128)*256; + }else{ + v=*(int8*)(seq->data+i*1); + v=v*128; + } + } + if (bps==2){ + if (seq->is_unsigned){ + v=*(uint16*)(seq->data+i*2); + v=v-32768; + }else{ + v=*(int16*)(seq->data+i*2); + } + } + //place new value into array + ((int16*)new_data)[i]=v; + }//i + if (bps!=2){free(seq->data); seq->data=new_data; seq->data_size=samples*2;} + //update seq info + seq->bits_per_sample=16; + seq->is_unsigned=0; + }//incorrect format -//2. samplerate conversion -if (seq->sample_rate != snd_frequency) { //need to resample seq->data - //create new resampler - SpeexResamplerState *state; - state = speex_resampler_init(seq->channels, seq->sample_rate, snd_frequency, SPEEX_RESAMPLER_QUALITY_MIN, NULL); - if (!state) { //NULL means failure - free(seq->data); - return 0; - } - - //allocate new memory for output - int32 out_samples_max = ((double)seq->data_size / seq->channels / 2) * ((((double)snd_frequency) / ((double)seq->sample_rate)) + 0.1) + 100;//10%+100 extra samples as a buffer-zone - int16 *resampled = (int16 *)malloc(out_samples_max * seq->channels * sizeof(int16)); - if (!resampled) { - free(seq->data); - return 0; - } - - //establish data sizes - //in_len will be set by the resampler to number of samples processed - spx_uint32_t in_len = seq->data_size / seq->channels / 2; // divide by 2 because 2byte samples, divive by #channels because function wants it per-channel - //out_len will be set to the number of samples written - spx_uint32_t out_len; - - //resample! - if (speex_resampler_process_interleaved_int(state, (spx_int16_t *)seq->data, &in_len, (spx_int16_t *)resampled, &out_len) != RESAMPLER_ERR_SUCCESS) { - //Error - free(resampled); - free(seq->data); - speex_resampler_destroy(state); - return 0; - } - - //destroy the resampler anyway - speex_resampler_destroy(state); - - //establish real size of new data and update seq - free(seq->data); //That was the old data - seq->data_size = out_len * seq->channels * 2; //remember out_len is perchannel, and each sample is 2 bytes - seq->data = (uint8_t *)realloc(resampled, seq->data_size); //we overestimated the array size before, so make it the correct size now - if (!seq->data) { //realloc could fail - free(resampled); - return 0; - } - seq->sample_rate = snd_frequency; -} + //2. samplerate conversion + if (seq->sample_rate != snd_frequency) { //need to resample seq->data + //create new resampler + SpeexResamplerState *state; + state = speex_resampler_init(seq->channels, seq->sample_rate, snd_frequency, SPEEX_RESAMPLER_QUALITY_MIN, NULL); + if (!state) { //NULL means failure + free(seq->data); + return 0; + } -if (seq->channels==1){ -seq->data_mono=seq->data; -seq->data_mono_size=seq->data_size; -} -if (seq->channels==2){ -seq->data_stereo=seq->data; -seq->data_stereo_size=seq->data_size; -} -if (seq->channels>2) return 0; + //allocate new memory for output + int32 out_samples_max = ((double)seq->data_size / seq->channels / 2) * ((((double)snd_frequency) / ((double)seq->sample_rate)) + 0.1) + 100;//10%+100 extra samples as a buffer-zone + int16 *resampled = (int16 *)malloc(out_samples_max * seq->channels * sizeof(int16)); + if (!resampled) { + free(seq->data); + return 0; + } -//attach sequence to handle (& inc. refs) -//create snd handle -static int32 handle; handle=list_add(snd_handles); -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + //establish data sizes + //in_len will be set by the resampler to number of samples processed + spx_uint32_t in_len = seq->data_size / seq->channels / 2; // divide by 2 because 2byte samples, divive by #channels because function wants it per-channel + //out_len will be set to the number of samples written + spx_uint32_t out_len; -snd->internal=0; -snd->type=2; -snd->seq=seq; -snd->volume=1.0; -snd->capability=r[0]*SND_CAPABILITY_SYNC+r[1]*SND_CAPABILITY_VOL+r[2]*SND_CAPABILITY_PAUSE+r[3]*SND_CAPABILITY_LEN+r[4]*SND_CAPABILITY_SETPOS; -if (!r[0]){ - snd->streamed=1;//NOT SYNC - snd_stream_handle=handle; -} + //resample! + if (speex_resampler_process_interleaved_int(state, (spx_int16_t *)seq->data, &in_len, (spx_int16_t *)resampled, &out_len) != RESAMPLER_ERR_SUCCESS) { + //Error + free(resampled); + free(seq->data); + speex_resampler_destroy(state); + return 0; + } -return handle; + //destroy the resampler anyway + speex_resampler_destroy(state); + + //establish real size of new data and update seq + free(seq->data); //That was the old data + seq->data_size = out_len * seq->channels * 2; //remember out_len is perchannel, and each sample is 2 bytes + seq->data = (uint8_t *)realloc(resampled, seq->data_size); //we overestimated the array size before, so make it the correct size now + if (!seq->data) { //realloc could fail + free(resampled); + return 0; + } + seq->sample_rate = snd_frequency; + } + + if (seq->channels==1){ + seq->data_mono=seq->data; + seq->data_mono_size=seq->data_size; + } + if (seq->channels==2){ + seq->data_stereo=seq->data; + seq->data_stereo_size=seq->data_size; + } + if (seq->channels>2) return 0; + + //attach sequence to handle (& inc. refs) + //create snd handle + static int32 handle; handle=list_add(snd_handles); + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + + snd->internal=0; + snd->type=2; + snd->seq=seq; + snd->volume=1.0; + snd->capability=r[0]*SND_CAPABILITY_SYNC+r[1]*SND_CAPABILITY_VOL+r[2]*SND_CAPABILITY_PAUSE+r[3]*SND_CAPABILITY_LEN+r[4]*SND_CAPABILITY_SETPOS; + if (!r[0]){ + snd->streamed=1;//NOT SYNC + snd_stream_handle=handle; + } + + return handle; } void sub__sndplayfile(qbs *filename,int32 sync,double volume,int32 passed){ -if (new_error) return; -sndsetup(); -static int32 handle; -static int32 setvolume; -static qbs *syncstr=NULL; if (!syncstr) syncstr=qbs_new(0,0); -setvolume=0; -if (passed&2){ -if ((volume<0)||(volume>1)){error(5); return;} -if (volume!=1) setvolume=1; -} -if ((!setvolume)&&(!sync)) syncstr->len=0; -if ((setvolume)&&(!sync)) qbs_set(syncstr,qbs_new_txt("VOL")); -if ((!setvolume)&&(sync)) qbs_set(syncstr,qbs_new_txt("SYNC")); -if ((setvolume)&&(sync)) qbs_set(syncstr,qbs_new_txt("SYNC,VOL")); -if (syncstr->len){ -handle=func__sndopen(filename,syncstr,1); -}else{ -handle=func__sndopen(filename,NULL,0); -} -if (handle==0) return; -if (setvolume) sub__sndvol(handle,volume); -sub__sndplay(handle); -sub__sndclose(handle); + if (new_error) return; + sndsetup(); + static int32 handle; + static int32 setvolume; + static qbs *syncstr=NULL; if (!syncstr) syncstr=qbs_new(0,0); + setvolume=0; + if (passed&2){ + if ((volume<0)||(volume>1)){error(5); return;} + if (volume!=1) setvolume=1; + } + if ((!setvolume)&&(!sync)) syncstr->len=0; + if ((setvolume)&&(!sync)) qbs_set(syncstr,qbs_new_txt("VOL")); + if ((!setvolume)&&(sync)) qbs_set(syncstr,qbs_new_txt("SYNC")); + if ((setvolume)&&(sync)) qbs_set(syncstr,qbs_new_txt("SYNC,VOL")); + if (syncstr->len){ + handle=func__sndopen(filename,syncstr,1); + }else{ + handle=func__sndopen(filename,NULL,0); + } + if (handle==0) return; + if (setvolume) sub__sndvol(handle,volume); + sub__sndplay(handle); + sub__sndclose(handle); } diff --git a/internal/c/parts/audio/out/src.c b/internal/c/parts/audio/out/src.c index 8bf88c0db..f5e90fe46 100644 --- a/internal/c/parts/audio/out/src.c +++ b/internal/c/parts/audio/out/src.c @@ -1,26 +1,26 @@ #ifndef DEPENDENCY_AUDIO_OUT - //Stubs: - void snd_mainloop(){return;} - void snd_init(){return;} - void snd_un_init(){return;} +//Stubs: +void snd_mainloop(){return;} +void snd_init(){return;} +void snd_un_init(){return;} #else #ifdef QB64_BACKSLASH_FILESYSTEM - #include "AL\\al.h" - #include "AL\\alc.h" - #include - #include - #include - #include - #include +#include "AL\\al.h" +#include "AL\\alc.h" +#include +#include +#include +#include +#include #else - #include "AL/al.h" - #include "AL/alc.h" - #include - #include - #include - #include - #include +#include "AL/al.h" +#include "AL/alc.h" +#include +#include +#include +#include +#include #endif //forward refs (with no struct dependencies) @@ -46,87 +46,87 @@ int32 snd_buffer_size=16384; int32 snd_allow_internal=0;//set this flag before calling snd_... commands with an internal sound uint8 *soundwave(double frequency,double length,double volume,double fadein,double fadeout){ -//this creates 16bit signed stereo data + //this creates 16bit signed stereo data -sndsetup(); -static uint8 *data; -static int32 i; -static int16 x,lastx; -static int16* sp; -static double samples_per_second; -samples_per_second=snd_frequency; + sndsetup(); + static uint8 *data; + static int32 i; + static int16 x,lastx; + static int16* sp; + static double samples_per_second; + samples_per_second=snd_frequency; -//calculate total number of samples required -static double samples; -static int32 samplesi; -samples=length*samples_per_second; -samplesi=samples; if (!samplesi) samplesi=1; + //calculate total number of samples required + static double samples; + static int32 samplesi; + samples=length*samples_per_second; + samplesi=samples; if (!samplesi) samplesi=1; -soundwave_bytes=samplesi*4; -data=(uint8*)malloc(soundwave_bytes); -sp=(int16*)data; + soundwave_bytes=samplesi*4; + data=(uint8*)malloc(soundwave_bytes); + sp=(int16*)data; -static int32 direction; -direction=1; + static int32 direction; + direction=1; -static double value; -value=0; + static double value; + value=0; -static double volume_multiplier; -volume_multiplier=volume*32767.0; + static double volume_multiplier; + volume_multiplier=volume*32767.0; -static int32 waveend; -waveend=0; + static int32 waveend; + waveend=0; -static double gradient; -//frequency*4.0*length is the total distance value will travel (+1,-2,+1[repeated]) -//samples is the number of steps to do this in -if (samples) gradient=(frequency*4.0*length)/samples; else gradient=0;//avoid division by 0 + static double gradient; + //frequency*4.0*length is the total distance value will travel (+1,-2,+1[repeated]) + //samples is the number of steps to do this in + if (samples) gradient=(frequency*4.0*length)/samples; else gradient=0;//avoid division by 0 -lastx=1;//set to 1 to avoid passing initial comparison -for (i=0;i0){ -if (lastx<=0){ -waveend=i; -} -} -lastx=x; -if (direction){ -if ((value+=gradient)>=1.0){direction=0; value=2.0-value;} -}else{ -if ((value-=gradient)<=-1.0){direction=1; value=-2.0-value;} -} -}//i + lastx=1;//set to 1 to avoid passing initial comparison + for (i=0;i0){ + if (lastx<=0){ + waveend=i; + } + } + lastx=x; + if (direction){ + if ((value+=gradient)>=1.0){direction=0; value=2.0-value;} + }else{ + if ((value-=gradient)<=-1.0){direction=1; value=-2.0-value;} + } + }//i -if (waveend) soundwave_bytes=waveend*4; + if (waveend) soundwave_bytes=waveend*4; -return (uint8*)data; + return (uint8*)data; } int32 wavesize(double length){ -static int32 samples; -samples=length*(double)snd_frequency; if (samples==0) samples=1; -return samples*4; + static int32 samples; + samples=length*(double)snd_frequency; if (samples==0) samples=1; + return samples*4; } void sub_sound(double frequency,double lengthinclockticks){ -sndsetup(); -if (new_error) return; -//note: there are 18.2 clock ticks per second -if ((frequency<37.0)&&(frequency!=0)) goto error; -if (frequency>32767.0) goto error; -if (lengthinclockticks<0.0) goto error; -if (lengthinclockticks>65535.0) goto error; -if (lengthinclockticks==0.0) return; -qb64_generatesound(frequency,lengthinclockticks/18.2,1); -return; + sndsetup(); + if (new_error) return; + //note: there are 18.2 clock ticks per second + if ((frequency<37.0)&&(frequency!=0)) goto error; + if (frequency>32767.0) goto error; + if (lengthinclockticks<0.0) goto error; + if (lengthinclockticks>65535.0) goto error; + if (lengthinclockticks==0.0) return; + qb64_generatesound(frequency,lengthinclockticks/18.2,1); + return; error: -error(5); + error(5); } @@ -136,109 +136,109 @@ error(5); struct snd_sequence_struct{ -uint8 *data; -int32 data_size; -uint8 channels;//note: more than 2 channels may be supported in the future -uint8 *data_stereo;//note: built/linked-to when available/required, otherwise NULL -int32 data_stereo_size; -uint8 *data_mono;//note: built/linked-to when available/required, otherwise NULL -int32 data_mono_size; + uint8 *data; + int32 data_size; + uint8 channels;//note: more than 2 channels may be supported in the future + uint8 *data_stereo;//note: built/linked-to when available/required, otherwise NULL + int32 data_stereo_size; + uint8 *data_mono;//note: built/linked-to when available/required, otherwise NULL + int32 data_mono_size; -//origins of data (only relevent before src) -uint8 endian;//0=native, 1=little(Windows, x86), 2=big(Motorola, Xilinx Microblaze, IBM POWER) -uint8 is_unsigned;//1=unsigned, 0=signed(most common) -int32 sample_rate;//eg. 11025, 22100 -int32 bits_per_sample;//eg. 8, 16 + //origins of data (only relevent before src) + uint8 endian;//0=native, 1=little(Windows, x86), 2=big(Motorola, Xilinx Microblaze, IBM POWER) + uint8 is_unsigned;//1=unsigned, 0=signed(most common) + int32 sample_rate;//eg. 11025, 22100 + int32 bits_per_sample;//eg. 8, 16 -int32 references;//number of SND handles dependent on this + int32 references;//number of SND handles dependent on this }; list *snd_sequences=list_new(sizeof(snd_sequence_struct)); struct snd_struct{ -uint8 internal;//1=internal -uint8 type;//1=RAW, 2=SEQUENCE -uint8 streamed;//1(NOT SYNC) or 0(SYNC) + uint8 internal;//1=internal + uint8 type;//1=RAW, 2=SEQUENCE + uint8 streamed;//1(NOT SYNC) or 0(SYNC) -//sequence -snd_sequence_struct *seq; - //----part specific variables---- - ALuint al_seq_buffer; - ALenum al_seq_format; - ALsizei al_seq_size; - ALsizei al_seq_freq; - ALboolean al_seq_loop; - ALvoid* al_seq_data; - ALuint al_seq_source; - //------------------------------- + //sequence + snd_sequence_struct *seq; + //----part specific variables---- + ALuint al_seq_buffer; + ALenum al_seq_format; + ALsizei al_seq_size; + ALsizei al_seq_freq; + ALboolean al_seq_loop; + ALvoid* al_seq_data; + ALuint al_seq_source; + //------------------------------- -float volume; -uint8 volume_update; - //----part specific variables---- - float al_volume; - //------------------------------- + float volume; + uint8 volume_update; + //----part specific variables---- + float al_volume; + //------------------------------- -uint8 use_mono; + uint8 use_mono; -uint8 close; + uint8 close; -uint8 limit_state;//0=off, 1=awaiting start[duration has been set], 2=waiting for stop point -double limit_duration; -int64 limit_stop_point; + uint8 limit_state;//0=off, 1=awaiting start[duration has been set], 2=waiting for stop point + double limit_duration; + int64 limit_stop_point; -//locks -uint8 setpos_lock_release; + //locks + uint8 setpos_lock_release; -uint8 setpos_update; -float setpos; + uint8 setpos_update; + float setpos; -float bal_x,bal_y,bal_z; -uint8 bal_update; - //----part specific variables---- - float al_bal_x,al_bal_y,al_bal_z; - //------------------------------- + float bal_x,bal_y,bal_z; + uint8 bal_update; + //----part specific variables---- + float al_bal_x,al_bal_y,al_bal_z; + //------------------------------- -//usage of buffer depends heavily on type -uint8 *buffer; -int32 buffer_size; + //usage of buffer depends heavily on type + uint8 *buffer; + int32 buffer_size; -ptrszint *stream_buffer;//pointers to buffers -int32 stream_buffer_last; -int32 stream_buffer_start; -int32 stream_buffer_next; + ptrszint *stream_buffer;//pointers to buffers + int32 stream_buffer_last; + int32 stream_buffer_start; + int32 stream_buffer_next; -ALuint al_source; -ALuint *al_buffers;//[4] -uint8 *al_buffer_state;//[4] 0=never used, 1=processing, 2=processed -int32 *al_buffer_index;//[4] + ALuint al_source; + ALuint *al_buffers;//[4] + uint8 *al_buffer_state;//[4] 0=never used, 1=processing, 2=processed + int32 *al_buffer_index;//[4] -int64 raw_close_time; + int64 raw_close_time; -//The maximum number of buffers on iOS and on OS X is 1024. -//The maximum number of sources is 32 on iOS and 256 on OS X. -//therefore: inactive sources should be de-initialized & buffers should be 4 + //The maximum number of buffers on iOS and on OS X is 1024. + //The maximum number of sources is 32 on iOS and 256 on OS X. + //therefore: inactive sources should be de-initialized & buffers should be 4 -uint8 capability; -uint8 state; + uint8 capability; + uint8 state; -//old stuff below...sigh! -uint8 free; -uint8 playing; -uint8 paused; -float volume_mult1; -float posx; -float posy; -float posz; -uint32 start_time; -uint32 paused_time; -uint8 looping; -uint32 limit; -double len; + //old stuff below...sigh! + uint8 free; + uint8 playing; + uint8 paused; + float volume_mult1; + float posx; + float posy; + float posz; + uint32 start_time; + uint32 paused_time; + uint8 looping; + uint32 limit; + double len; }; @@ -257,33 +257,33 @@ int32 snd_stream_handle=0;//only one sound can be streamed void sndsetup(){ -static int32 sndsetup_called=0; -if (!sndsetup_called){ -sndsetup_called=1; -//... -} + static int32 sndsetup_called=0; + if (!sndsetup_called){ + sndsetup_called=1; + //... + } -//scan through all sounds and close marked ones, performed here to avoid thread issues -static int32 list_index; -for (list_index=1;list_index<=snd_handles->indexes;list_index++){ -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,list_index); -if (snd){ + //scan through all sounds and close marked ones, performed here to avoid thread issues + static int32 list_index; + for (list_index=1;list_index<=snd_handles->indexes;list_index++){ + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,list_index); + if (snd){ -if (snd->close==2){ - sndclose_now(list_index); -} + if (snd->close==2){ + sndclose_now(list_index); + } -}//snd -}//list_index + }//snd + }//list_index }//sndsetup void sub_beep(){ -sndsetup(); -qb64_generatesound(783.99,0.2,0); -sub__delay(0.25); + sndsetup(); + qb64_generatesound(783.99,0.2,0); + sub__delay(0.25); } @@ -292,29 +292,29 @@ sub__delay(0.25); ALCdevice *dev; ALCcontext *ctx; struct stat statbuf; - -void snd_un_init(){ -alcCloseDevice(dev); -return; -} + +void snd_un_init(){ + alcCloseDevice(dev); + return; +} int32 snd_init_done=0; void snd_init(){ -if (!snd_init_done){ + if (!snd_init_done){ -dev = alcOpenDevice(NULL); if(!dev) exit(111); -ctx = alcCreateContext(dev, NULL); -alcMakeContextCurrent(ctx); if(!ctx) exit(222); + dev = alcOpenDevice(NULL); if(!dev) exit(111); + ctx = alcCreateContext(dev, NULL); + alcMakeContextCurrent(ctx); if(!ctx) exit(222); -alListener3f(AL_POSITION, 0, 0, 0); -alListener3f(AL_VELOCITY, 0, 0, 0); -alListener3f(AL_ORIENTATION, 0, 0, -1);//facing 'forward' on rhs co-ordinate system -alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); + alListener3f(AL_POSITION, 0, 0, 0); + alListener3f(AL_VELOCITY, 0, 0, 0); + alListener3f(AL_ORIENTATION, 0, 0, -1);//facing 'forward' on rhs co-ordinate system + alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); -} -snd_init_done=1; + } + snd_init_done=1; } @@ -326,27 +326,27 @@ int32 snd_raw_channel=0; int32 func__sndopenraw(){ -static int32 handle; handle=list_add(snd_handles); -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -snd->internal=0; -snd->type=1; -snd->buffer=(uint8*)malloc(snd_buffer_size); -snd->buffer_size=0; + static int32 handle; handle=list_add(snd_handles); + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + snd->internal=0; + snd->type=1; + snd->buffer=(uint8*)malloc(snd_buffer_size); + snd->buffer_size=0; -snd->stream_buffer_last=65536; -snd->stream_buffer=(ptrszint*)malloc(sizeof(ptrszint)*(snd->stream_buffer_last+1));//range: 1-65536 (0 ignored) -snd->stream_buffer_start=0; -snd->stream_buffer_next=1; + snd->stream_buffer_last=65536; + snd->stream_buffer=(ptrszint*)malloc(sizeof(ptrszint)*(snd->stream_buffer_last+1));//range: 1-65536 (0 ignored) + snd->stream_buffer_start=0; + snd->stream_buffer_next=1; -alGenSources(1,&snd->al_source); -//if(alGetError()!=AL_NO_ERROR) return 0; + alGenSources(1,&snd->al_source); + //if(alGetError()!=AL_NO_ERROR) return 0; -snd->al_buffers=(ALuint*)malloc(sizeof(ALuint)*4); -alGenBuffers(4,snd->al_buffers); -//if(alGetError()!=AL_NO_ERROR) return 0; -snd->al_buffer_state=(uint8*)calloc(4,1); -snd->al_buffer_index=(int32*)calloc(4,4); -return handle; + snd->al_buffers=(ALuint*)malloc(sizeof(ALuint)*4); + alGenBuffers(4,snd->al_buffers); + //if(alGetError()!=AL_NO_ERROR) return 0; + snd->al_buffer_state=(uint8*)calloc(4,1); + snd->al_buffer_index=(int32*)calloc(4,4); + return handle; } @@ -355,270 +355,270 @@ return handle; void sub__sndraw(float left,float right,int32 handle,int32 passed){ -if (passed&2){ - if (handle==0) return;//note: this would be an invalid handle -}else{ - if (!snd_raw_channel) snd_raw_channel=func__sndopenraw(); - handle=snd_raw_channel; -} + if (passed&2){ + if (handle==0) return;//note: this would be an invalid handle + }else{ + if (!snd_raw_channel) snd_raw_channel=func__sndopenraw(); + handle=snd_raw_channel; + } -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd) goto error; -if (snd->internal) goto error; -if (snd->type!=1) goto error; + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd) goto error; + if (snd->internal) goto error; + if (snd->type!=1) goto error; -while (qb64_sndraw_lock) Sleep(0); -qb64_sndraw_lock=1; + while (qb64_sndraw_lock) Sleep(0); + qb64_sndraw_lock=1; -if (handle==qb64_internal_sndraw_handle) qb64_internal_sndraw_lastcall=GetTicks(); + if (handle==qb64_internal_sndraw_handle) qb64_internal_sndraw_lastcall=GetTicks(); -static int16 sample_left; -sample_left=left*32767.0; -static int16 sample_right; -if (passed&1) sample_right=right*32767.0; else sample_right=sample_left; + static int16 sample_left; + sample_left=left*32767.0; + static int16 sample_right; + if (passed&1) sample_right=right*32767.0; else sample_right=sample_left; -//add sample -if (snd->buffer_sizebuffer+snd->buffer_size)=sample_left; -snd->buffer_size+=2; -*(int16*)(snd->buffer+snd->buffer_size)=sample_right; -snd->buffer_size+=2; -} + //add sample + if (snd->buffer_sizebuffer+snd->buffer_size)=sample_left; + snd->buffer_size+=2; + *(int16*)(snd->buffer+snd->buffer_size)=sample_right; + snd->buffer_size+=2; + } -if (snd->buffer_size==snd_buffer_size){ -//detach buffer -static uint8 *buffer; -buffer=snd->buffer; + if (snd->buffer_size==snd_buffer_size){ + //detach buffer + static uint8 *buffer; + buffer=snd->buffer; -//create new buffer -snd->buffer=(uint8*)malloc(snd_buffer_size); -snd->buffer_size=0; + //create new buffer + snd->buffer=(uint8*)malloc(snd_buffer_size); + snd->buffer_size=0; -//attach detached buffer to stream (or discard it) -static int32 p,p2; -p=snd->stream_buffer_next; p2=p+1; if (p2>snd->stream_buffer_last) p2=1; -if (p2==snd->stream_buffer_start){free(buffer); qb64_sndraw_lock=0; return;}//all buffers are full! (quietly ignore this buffer) -snd->stream_buffer[p]=(ptrszint)buffer; -snd->stream_buffer_next=p2; -if (!snd->stream_buffer_start) snd->stream_buffer_start=1; + //attach detached buffer to stream (or discard it) + static int32 p,p2; + p=snd->stream_buffer_next; p2=p+1; if (p2>snd->stream_buffer_last) p2=1; + if (p2==snd->stream_buffer_start){free(buffer); qb64_sndraw_lock=0; return;}//all buffers are full! (quietly ignore this buffer) + snd->stream_buffer[p]=(ptrszint)buffer; + snd->stream_buffer_next=p2; + if (!snd->stream_buffer_start) snd->stream_buffer_start=1; -} + } -qb64_sndraw_lock=0; + qb64_sndraw_lock=0; -return; + return; error: -error(5); -return; + error(5); + return; } void snd_mainloop(){ -static int64 t; -t=-1; + static int64 t; + t=-1; -//scan through all sounds -static int32 list_index; -for (list_index=1;list_index<=snd_handles->indexes;list_index++){ -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,list_index); -if (snd){ + //scan through all sounds + static int32 list_index; + for (list_index=1;list_index<=snd_handles->indexes;list_index++){ + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,list_index); + if (snd){ -if (snd->type==2){ + if (snd->type==2){ - if (snd->limit_state==2){ - if (t==-1) t=GetTicks(); - if (t>=snd->limit_stop_point){snd->limit_state=0; sub__sndstop(list_index);} - }//limit_state==2 + if (snd->limit_state==2){ + if (t==-1) t=GetTicks(); + if (t>=snd->limit_stop_point){snd->limit_state=0; sub__sndstop(list_index);} + }//limit_state==2 - if (snd->close==1){ - //directly poll to check the sound's state - static ALint al_state; - alGetSourcei(snd->al_seq_source,AL_SOURCE_STATE,&al_state); - if (al_state==AL_INITIAL) snd->state=SND_STATE_STOPPED; - if (al_state==AL_STOPPED) snd->state=SND_STATE_STOPPED; - if (al_state==AL_PLAYING) snd->state=SND_STATE_PLAYING; - if (al_state==AL_PAUSED) snd->state=SND_STATE_PAUSED; - if (snd->state!=SND_STATE_PLAYING) snd->close=2; - }//snd->close==1 + if (snd->close==1){ + //directly poll to check the sound's state + static ALint al_state; + alGetSourcei(snd->al_seq_source,AL_SOURCE_STATE,&al_state); + if (al_state==AL_INITIAL) snd->state=SND_STATE_STOPPED; + if (al_state==AL_STOPPED) snd->state=SND_STATE_STOPPED; + if (al_state==AL_PLAYING) snd->state=SND_STATE_PLAYING; + if (al_state==AL_PAUSED) snd->state=SND_STATE_PAUSED; + if (snd->state!=SND_STATE_PLAYING) snd->close=2; + }//snd->close==1 -}//2 + }//2 -if (snd->type==1){//RAW + if (snd->type==1){//RAW -if (snd->close!=2){ + if (snd->close!=2){ -if (snd->stream_buffer_start){ + if (snd->stream_buffer_start){ -static int32 repeat; -do{ -repeat=0; + static int32 repeat; + do{ + repeat=0; -//internal sndraw post padding -//note: without post padding the final, incomplete buffer of sound data would not be played -if (list_index==qb64_internal_sndraw_handle){//internal sound raw -if (snd->stream_buffer_start==snd->stream_buffer_next){//on last source buffer -if (snd->buffer_size>0){//partial size -if (GetTicks()>(qb64_internal_sndraw_lastcall+20)){//no input received for last 0.02 seconds -if (!qb64_sndraw_lock){//lock (or skip) -qb64_sndraw_lock=1; -if (qb64_internal_sndraw_postpad){//post-pad allowed -qb64_internal_sndraw_postpad=0; -while (snd->buffer_sizebuffer+snd->buffer_size)=0; - snd->buffer_size+=2; - *(int16*)(snd->buffer+snd->buffer_size)=0; - snd->buffer_size+=2; -} -//detach buffer - static uint8 *buffer; - buffer=snd->buffer; -//create new buffer - snd->buffer=(uint8*)calloc(snd_buffer_size,1); - snd->buffer_size=0; -//attach detached buffer to stream (or discard it) - static int32 p,p2; - p=snd->stream_buffer_next; p2=p+1; if (p2>snd->stream_buffer_last) p2=1; - if (p2==snd->stream_buffer_start){ - free(buffer); //all buffers are full! (quietly ignore this buffer) - }else{ - snd->stream_buffer[p]=(ptrszint)buffer; - snd->stream_buffer_next=p2; - } -//next sound command to prepad if necessary to begin sound - qb64_internal_sndraw_prepad=1; -//unlock - qb64_sndraw_lock=0; -}//post-pad allowed -}//lock (or skip) -}//no input received for last x seconds -}//partial size -}//on last source buffer -}//internal sound raw + //internal sndraw post padding + //note: without post padding the final, incomplete buffer of sound data would not be played + if (list_index==qb64_internal_sndraw_handle){//internal sound raw + if (snd->stream_buffer_start==snd->stream_buffer_next){//on last source buffer + if (snd->buffer_size>0){//partial size + if (GetTicks()>(qb64_internal_sndraw_lastcall+20)){//no input received for last 0.02 seconds + if (!qb64_sndraw_lock){//lock (or skip) + qb64_sndraw_lock=1; + if (qb64_internal_sndraw_postpad){//post-pad allowed + qb64_internal_sndraw_postpad=0; + while (snd->buffer_sizebuffer+snd->buffer_size)=0; + snd->buffer_size+=2; + *(int16*)(snd->buffer+snd->buffer_size)=0; + snd->buffer_size+=2; + } + //detach buffer + static uint8 *buffer; + buffer=snd->buffer; + //create new buffer + snd->buffer=(uint8*)calloc(snd_buffer_size,1); + snd->buffer_size=0; + //attach detached buffer to stream (or discard it) + static int32 p,p2; + p=snd->stream_buffer_next; p2=p+1; if (p2>snd->stream_buffer_last) p2=1; + if (p2==snd->stream_buffer_start){ + free(buffer); //all buffers are full! (quietly ignore this buffer) + }else{ + snd->stream_buffer[p]=(ptrszint)buffer; + snd->stream_buffer_next=p2; + } + //next sound command to prepad if necessary to begin sound + qb64_internal_sndraw_prepad=1; + //unlock + qb64_sndraw_lock=0; + }//post-pad allowed + }//lock (or skip) + }//no input received for last x seconds + }//partial size + }//on last source buffer + }//internal sound raw -if (snd->stream_buffer_start!=snd->stream_buffer_next){ -static int32 p,p2; -static int32 i,i2; -p=snd->stream_buffer_start; p2=p+1; if (p2>snd->stream_buffer_last) p2=1; + if (snd->stream_buffer_start!=snd->stream_buffer_next){ + static int32 p,p2; + static int32 i,i2; + p=snd->stream_buffer_start; p2=p+1; if (p2>snd->stream_buffer_last) p2=1; -//unqueue processed buffers (if any) -static ALint buffers_processed; -static ALuint buffers[4]; -alGetSourcei(snd->al_source, AL_BUFFERS_PROCESSED, &buffers_processed); -if (buffers_processed){ -alSourceUnqueueBuffers(snd->al_source, buffers_processed, &buffers[0]); - //free associated data - for (i2=0;i2al_buffers[i]){ - free((void*)snd->stream_buffer[snd->al_buffer_index[i]]); - snd->al_buffer_state[i]=2;//"processed" - } - } - } -} + //unqueue processed buffers (if any) + static ALint buffers_processed; + static ALuint buffers[4]; + alGetSourcei(snd->al_source, AL_BUFFERS_PROCESSED, &buffers_processed); + if (buffers_processed){ + alSourceUnqueueBuffers(snd->al_source, buffers_processed, &buffers[0]); + //free associated data + for (i2=0;i2al_buffers[i]){ + free((void*)snd->stream_buffer[snd->al_buffer_index[i]]); + snd->al_buffer_state[i]=2;//"processed" + } + } + } + } -//check for uninitiated buffers -for (i=0;i<=3;i++){ -if (snd->al_buffer_state[i]==0){ -snd->al_buffer_state[i]=1;//"processing" -snd->al_buffer_index[i]=p; -static ALuint frequency; -static ALenum format; -frequency=snd_frequency; -format=AL_FORMAT_STEREO16; -alBufferData(snd->al_buffers[i], format, (void*)snd->stream_buffer[p], snd_buffer_size, frequency); -alSourceQueueBuffers(snd->al_source, 1, &snd->al_buffers[i]); - static ALint al_state; - alGetSourcei(snd->al_source,AL_SOURCE_STATE,&al_state); - if (al_state!=AL_PLAYING){ - alSourcePlay(snd->al_source); - } -goto gotbuffer; -} -} + //check for uninitiated buffers + for (i=0;i<=3;i++){ + if (snd->al_buffer_state[i]==0){ + snd->al_buffer_state[i]=1;//"processing" + snd->al_buffer_index[i]=p; + static ALuint frequency; + static ALenum format; + frequency=snd_frequency; + format=AL_FORMAT_STEREO16; + alBufferData(snd->al_buffers[i], format, (void*)snd->stream_buffer[p], snd_buffer_size, frequency); + alSourceQueueBuffers(snd->al_source, 1, &snd->al_buffers[i]); + static ALint al_state; + alGetSourcei(snd->al_source,AL_SOURCE_STATE,&al_state); + if (al_state!=AL_PLAYING){ + alSourcePlay(snd->al_source); + } + goto gotbuffer; + } + } -//check for finished buffers -for (i=0;i<=3;i++){ -if (snd->al_buffer_state[i]==2){//"processed" -static ALuint buffer; -static ALuint frequency; -static ALenum format; -frequency=snd_frequency; -format=AL_FORMAT_STEREO16; -alBufferData(snd->al_buffers[i], format, (void*)snd->stream_buffer[p], snd_buffer_size, frequency); -alSourceQueueBuffers(snd->al_source, 1, &snd->al_buffers[i]); - static ALint al_state; - alGetSourcei(snd->al_source,AL_SOURCE_STATE,&al_state); - if (al_state!=AL_PLAYING){ - alSourcePlay(snd->al_source); - } -snd->al_buffer_index[i]=p; -snd->al_buffer_state[i]=1;//"processing" -goto gotbuffer; -} -} + //check for finished buffers + for (i=0;i<=3;i++){ + if (snd->al_buffer_state[i]==2){//"processed" + static ALuint buffer; + static ALuint frequency; + static ALenum format; + frequency=snd_frequency; + format=AL_FORMAT_STEREO16; + alBufferData(snd->al_buffers[i], format, (void*)snd->stream_buffer[p], snd_buffer_size, frequency); + alSourceQueueBuffers(snd->al_source, 1, &snd->al_buffers[i]); + static ALint al_state; + alGetSourcei(snd->al_source,AL_SOURCE_STATE,&al_state); + if (al_state!=AL_PLAYING){ + alSourcePlay(snd->al_source); + } + snd->al_buffer_index[i]=p; + snd->al_buffer_state[i]=1;//"processing" + goto gotbuffer; + } + } -i=-1; + i=-1; gotbuffer: -if (i!=-1){ - repeat=1; - snd->stream_buffer_start=p2; -} + if (i!=-1){ + repeat=1; + snd->stream_buffer_start=p2; + } -}//queued buffer exists + }//queued buffer exists -}while(repeat); + }while(repeat); -}//started -}//close!=2 + }//started + }//close!=2 -//close raw? -if (snd->close==1){ -if (t==-1) t=GetTicks(); -if (t>(snd->raw_close_time+3000)){ - static ALint al_state; - alGetSourcei(snd->al_source,AL_SOURCE_STATE,&al_state); - if (al_state==AL_INITIAL) snd->state=SND_STATE_STOPPED; - if (al_state==AL_STOPPED) snd->state=SND_STATE_STOPPED; - if (al_state==AL_PLAYING) snd->state=SND_STATE_PLAYING; - if (al_state==AL_PAUSED) snd->state=SND_STATE_PAUSED; - if (snd->state!=SND_STATE_PLAYING){//not playing - //note: hardware interface parts closed here, handles closed in sndclose_now - if (snd->al_source){ - alDeleteSources(1,&snd->al_source); snd->al_source=0; - } - static int32 i; - for (i=0;i<=3;i++){ - if (snd->al_buffers[i]) alDeleteBuffers(1,&snd->al_buffers[i]); - } - //remove the buffers - //1)remove 4 AL buffers - free(snd->al_buffers); - free(snd->al_buffer_index); - free(snd->al_buffer_state); - //2)remove build buffer - free(snd->buffer); - //3)remove the 65536 pointers to potential buffers - free(snd->stream_buffer); - snd->close=2; - }//not playing -}//time>3 secs -}//sndclose==1 + //close raw? + if (snd->close==1){ + if (t==-1) t=GetTicks(); + if (t>(snd->raw_close_time+3000)){ + static ALint al_state; + alGetSourcei(snd->al_source,AL_SOURCE_STATE,&al_state); + if (al_state==AL_INITIAL) snd->state=SND_STATE_STOPPED; + if (al_state==AL_STOPPED) snd->state=SND_STATE_STOPPED; + if (al_state==AL_PLAYING) snd->state=SND_STATE_PLAYING; + if (al_state==AL_PAUSED) snd->state=SND_STATE_PAUSED; + if (snd->state!=SND_STATE_PLAYING){//not playing + //note: hardware interface parts closed here, handles closed in sndclose_now + if (snd->al_source){ + alDeleteSources(1,&snd->al_source); snd->al_source=0; + } + static int32 i; + for (i=0;i<=3;i++){ + if (snd->al_buffers[i]) alDeleteBuffers(1,&snd->al_buffers[i]); + } + //remove the buffers + //1)remove 4 AL buffers + free(snd->al_buffers); + free(snd->al_buffer_index); + free(snd->al_buffer_state); + //2)remove build buffer + free(snd->buffer); + //3)remove the 65536 pointers to potential buffers + free(snd->stream_buffer); + snd->close=2; + }//not playing + }//time>3 secs + }//sndclose==1 -}//RAW + }//RAW -}//snd -}//list_index loop + }//snd + }//list_index loop @@ -642,46 +642,46 @@ if (t>(snd->raw_close_time+3000)){ #define SND_CAPABILITY_SETPOS 16 /* -struct snd_struct{ -uint32 handle; -Mix_Chunk *sample; -uint8 free; -uint8 playing; -uint8 paused; -float volume; -float volume_mult1; -float posx; -float posy; -float posz; -uint32 start_time; -uint32 paused_time; -uint8 looping; -uint32 limit; -double len; -uint8 capability; -}; -snd_struct snd[AUDIO_CHANNELS]; -Mix_Music *stream=NULL; -int32 stream_free=0; -int32 stream_loaded=0; -int32 stream_playing=0; -uint32 snd_free_handle=2; -int32 stream_type=0; -int32 stream_paused=0; -float stream_volume=1; -float stream_volume_mult1=1; -uint32 stream_start_time=0; -uint32 stream_paused_time=0; -double stream_setpos=0; -int32 stream_looping=0; -double stream_limit=0; -int32 stream_limited=0; -double stream_len=-1; -uint8 stream_capability; + struct snd_struct{ + uint32 handle; + Mix_Chunk *sample; + uint8 free; + uint8 playing; + uint8 paused; + float volume; + float volume_mult1; + float posx; + float posy; + float posz; + uint32 start_time; + uint32 paused_time; + uint8 looping; + uint32 limit; + double len; + uint8 capability; + }; + snd_struct snd[AUDIO_CHANNELS]; + Mix_Music *stream=NULL; + int32 stream_free=0; + int32 stream_loaded=0; + int32 stream_playing=0; + uint32 snd_free_handle=2; + int32 stream_type=0; + int32 stream_paused=0; + float stream_volume=1; + float stream_volume_mult1=1; + uint32 stream_start_time=0; + uint32 stream_paused_time=0; + double stream_setpos=0; + int32 stream_looping=0; + double stream_limit=0; + int32 stream_limited=0; + double stream_len=-1; + uint8 stream_capability; -void snd_check(){ -sndsetup(); -static int32 i,i2,i3; + void snd_check(){ + sndsetup(); + static int32 i,i2,i3; //check stream if (stream_loaded){ if (stream_free){ @@ -720,25 +720,25 @@ if (i3) Mix_FreeChunk(snd[i].sample); uint32 func__sndraw(uint8* data,uint32 bytes){ -sndsetup(); -//***unavailable to QB64 user*** -static int32 i,i2,i3; -//find available index -for (i=0;ialen)/22050.0/2.0/2.0; -snd[i].handle=snd_free_handle; snd_free_handle++; if (snd_free_handle==0) snd_free_handle=2; -snd[i].capability=SND_CAPABILITY_SYNC; -return snd[i].handle; -} -} -return 0;//no free indexes + sndsetup(); + //***unavailable to QB64 user*** + static int32 i,i2,i3; + //find available index + for (i=0;ialen)/22050.0/2.0/2.0; + snd[i].handle=snd_free_handle; snd_free_handle++; if (snd_free_handle==0) snd_free_handle=2; + snd[i].capability=SND_CAPABILITY_SYNC; + return snd[i].handle; + } + } + return 0;//no free indexes } */ @@ -759,158 +759,158 @@ return 0;//no free indexes int32 sndupdate_dont_free_resources=0; void sndupdate(snd_struct *snd){ -if (snd->type==2){//seq type -static snd_sequence_struct *seq; seq=snd->seq; -if (snd->al_seq_source){ -//update state info -static ALint al_state; -alGetSourcei(snd->al_seq_source,AL_SOURCE_STATE,&al_state); -//ref: Each source can be in one of four possible execution states: AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED -if (al_state==AL_INITIAL) snd->state=SND_STATE_STOPPED; -if (al_state==AL_STOPPED) snd->state=SND_STATE_STOPPED; -if (al_state==AL_PLAYING) snd->state=SND_STATE_PLAYING; -if (al_state==AL_PAUSED) snd->state=SND_STATE_PAUSED; -if (snd->state==SND_STATE_STOPPED){ -if (!sndupdate_dont_free_resources){ - if (snd->setpos_lock_release) goto no_release; - //###agressively free OpenAL resources (buffers & sources are very limited on some platforms)### - alDeleteSources(1,&snd->al_seq_source); snd->al_seq_source=0; - alDeleteBuffers(1,&snd->al_seq_buffer); snd->al_seq_buffer=0; - //flag updates - snd->volume_update=1; - snd->bal_update=1; - no_release:; -} -} -if (snd->limit_state==2){ - if (snd->state!=SND_STATE_PLAYING) snd->limit_state=0;//disable limit -} -if (snd->al_seq_source){//still valid? -if (snd->bal_update){ - snd->bal_update=0; - if (snd->bal_y||snd->bal_z){ - snd->use_mono=1; - } - if ((!snd->use_mono)||(!seq->data_mono)){//2D repositioning - if (seq->data_stereo){ - //note: OpenAL would ignore our call so use a volume change to simulate distance - static double d; - d=sqrt(snd->bal_x*snd->bal_x+snd->bal_y*snd->bal_y+snd->bal_z*snd->bal_z); - if (d<1) d=0; - if (d>1000) d=1000; - d=1000-d; - d=d/1000.0;//'d' is now a scaling factor from 0 to 1 - d=d*((double)snd->volume); - alSourcef(snd->al_seq_source,AL_GAIN,d); - snd->volume_update=0;//cancel possible volume update - goto skip_bal_change; - } - } - //rescale our audio co-ordinate system (-1000[-1] to [1]1000) to match OpenAL(-10[-0.01] to [0.01]10) - snd->al_bal_x=snd->bal_x/100.0; - snd->al_bal_y=snd->bal_y/100.0; - snd->al_bal_z=-(snd->bal_z/100.0); - alSource3f(snd->al_seq_source, AL_POSITION, snd->al_bal_x, snd->al_bal_y, snd->al_bal_z); - skip_bal_change:; - /* - OpenAL -- like OpenGL -- uses a right-handed Cartesian coordinate system (RHS), - where in a frontal default view X (thumb) points right, Y (index finger) points up, - and Z (middle finger) points towards the viewer/camera. To switch from a left handed - coordinate system (LHS) to a right handed coordinate systems, flip the sign on the Z coordinate. - */ - /* ref: old bal system code & notes - x distance values go from left(negative) to right(positive). - y distance values go from below(negative) to above(positive). - z distance values go from behind(negative) to in front(positive). - d=sqrt(x*x+y*y+z*z); - if (d<1) d=0; - if (d>1000) d=1000; - d=1000-d; - d=d/1000.0; - stream_volume_mult1=d; - -------------------- - snd[i].posx=x; snd[i].posy=y; snd[i].posz=z; - d=atan2(x,z)*57.295779513; - if (d<0) d=360+d; - i2=d+0.5; if (i2==360) i2=0;//angle - d2=sqrt(x*x+y*y+z*z);//distance - if (d2<1) d2=1; - if (d2>999.9) d2=999.9; - i3=d2/3.90625; - */ -}//snd->bal_update -if (snd->volume_update){ - snd->volume_update=0; - snd->al_volume=snd->volume; - if (snd->bal_x&&((!snd->use_mono)||(!seq->data_mono))){ - if (seq->data_stereo){ - static double d; - d=sqrt(snd->al_bal_x*snd->al_bal_x+snd->al_bal_y*snd->al_bal_y+snd->al_bal_z*snd->al_bal_z); - if (d<1) d=0; - if (d>1000) d=1000; - d=1000-d; - d=d/1000.0;//'d' is now a scaling factor from 0 to 1 - d=d*((double)snd->volume); - alSourcef(snd->al_seq_source,AL_GAIN,d); - goto skip_regular_vol_change; - } - } - alSourcef(snd->al_seq_source,AL_GAIN,snd->al_volume); - skip_regular_vol_change:; -}//snd->volume_update -if (snd->setpos_lock_release){ -if (snd->state!=SND_STATE_STOPPED){ -snd->setpos_lock_release=0; -} -} -if (snd->setpos_update){ -snd->setpos_update=0; -alSourcef(snd->al_seq_source,AL_SEC_OFFSET,snd->setpos); -snd->setpos_lock_release=1; -} -}//snd->al_seq_source still valid? -}//snd->al_seq_source -}//2 + if (snd->type==2){//seq type + static snd_sequence_struct *seq; seq=snd->seq; + if (snd->al_seq_source){ + //update state info + static ALint al_state; + alGetSourcei(snd->al_seq_source,AL_SOURCE_STATE,&al_state); + //ref: Each source can be in one of four possible execution states: AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED + if (al_state==AL_INITIAL) snd->state=SND_STATE_STOPPED; + if (al_state==AL_STOPPED) snd->state=SND_STATE_STOPPED; + if (al_state==AL_PLAYING) snd->state=SND_STATE_PLAYING; + if (al_state==AL_PAUSED) snd->state=SND_STATE_PAUSED; + if (snd->state==SND_STATE_STOPPED){ + if (!sndupdate_dont_free_resources){ + if (snd->setpos_lock_release) goto no_release; + //###agressively free OpenAL resources (buffers & sources are very limited on some platforms)### + alDeleteSources(1,&snd->al_seq_source); snd->al_seq_source=0; + alDeleteBuffers(1,&snd->al_seq_buffer); snd->al_seq_buffer=0; + //flag updates + snd->volume_update=1; + snd->bal_update=1; +no_release:; + } + } + if (snd->limit_state==2){ + if (snd->state!=SND_STATE_PLAYING) snd->limit_state=0;//disable limit + } + if (snd->al_seq_source){//still valid? + if (snd->bal_update){ + snd->bal_update=0; + if (snd->bal_y||snd->bal_z){ + snd->use_mono=1; + } + if ((!snd->use_mono)||(!seq->data_mono)){//2D repositioning + if (seq->data_stereo){ + //note: OpenAL would ignore our call so use a volume change to simulate distance + static double d; + d=sqrt(snd->bal_x*snd->bal_x+snd->bal_y*snd->bal_y+snd->bal_z*snd->bal_z); + if (d<1) d=0; + if (d>1000) d=1000; + d=1000-d; + d=d/1000.0;//'d' is now a scaling factor from 0 to 1 + d=d*((double)snd->volume); + alSourcef(snd->al_seq_source,AL_GAIN,d); + snd->volume_update=0;//cancel possible volume update + goto skip_bal_change; + } + } + //rescale our audio co-ordinate system (-1000[-1] to [1]1000) to match OpenAL(-10[-0.01] to [0.01]10) + snd->al_bal_x=snd->bal_x/100.0; + snd->al_bal_y=snd->bal_y/100.0; + snd->al_bal_z=-(snd->bal_z/100.0); + alSource3f(snd->al_seq_source, AL_POSITION, snd->al_bal_x, snd->al_bal_y, snd->al_bal_z); +skip_bal_change:; + /* + OpenAL -- like OpenGL -- uses a right-handed Cartesian coordinate system (RHS), + where in a frontal default view X (thumb) points right, Y (index finger) points up, + and Z (middle finger) points towards the viewer/camera. To switch from a left handed + coordinate system (LHS) to a right handed coordinate systems, flip the sign on the Z coordinate. + */ + /* ref: old bal system code & notes + x distance values go from left(negative) to right(positive). + y distance values go from below(negative) to above(positive). + z distance values go from behind(negative) to in front(positive). + d=sqrt(x*x+y*y+z*z); + if (d<1) d=0; + if (d>1000) d=1000; + d=1000-d; + d=d/1000.0; + stream_volume_mult1=d; + -------------------- + snd[i].posx=x; snd[i].posy=y; snd[i].posz=z; + d=atan2(x,z)*57.295779513; + if (d<0) d=360+d; + i2=d+0.5; if (i2==360) i2=0;//angle + d2=sqrt(x*x+y*y+z*z);//distance + if (d2<1) d2=1; + if (d2>999.9) d2=999.9; + i3=d2/3.90625; + */ + }//snd->bal_update + if (snd->volume_update){ + snd->volume_update=0; + snd->al_volume=snd->volume; + if (snd->bal_x&&((!snd->use_mono)||(!seq->data_mono))){ + if (seq->data_stereo){ + static double d; + d=sqrt(snd->al_bal_x*snd->al_bal_x+snd->al_bal_y*snd->al_bal_y+snd->al_bal_z*snd->al_bal_z); + if (d<1) d=0; + if (d>1000) d=1000; + d=1000-d; + d=d/1000.0;//'d' is now a scaling factor from 0 to 1 + d=d*((double)snd->volume); + alSourcef(snd->al_seq_source,AL_GAIN,d); + goto skip_regular_vol_change; + } + } + alSourcef(snd->al_seq_source,AL_GAIN,snd->al_volume); +skip_regular_vol_change:; + }//snd->volume_update + if (snd->setpos_lock_release){ + if (snd->state!=SND_STATE_STOPPED){ + snd->setpos_lock_release=0; + } + } + if (snd->setpos_update){ + snd->setpos_update=0; + alSourcef(snd->al_seq_source,AL_SEC_OFFSET,snd->setpos); + snd->setpos_lock_release=1; + } + }//snd->al_seq_source still valid? + }//snd->al_seq_source + }//2 -if (snd->type==1){ -static ALint al_state; -alGetSourcei(snd->al_source,AL_SOURCE_STATE,&al_state); -//ref: Each source can be in one of four possible execution states: AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED -if (al_state==AL_INITIAL) snd->state=SND_STATE_STOPPED; -if (al_state==AL_STOPPED) snd->state=SND_STATE_STOPPED; -if (al_state==AL_PLAYING) snd->state=SND_STATE_PLAYING; -if (al_state==AL_PAUSED) snd->state=SND_STATE_PAUSED; -} + if (snd->type==1){ + static ALint al_state; + alGetSourcei(snd->al_source,AL_SOURCE_STATE,&al_state); + //ref: Each source can be in one of four possible execution states: AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED + if (al_state==AL_INITIAL) snd->state=SND_STATE_STOPPED; + if (al_state==AL_STOPPED) snd->state=SND_STATE_STOPPED; + if (al_state==AL_PLAYING) snd->state=SND_STATE_PLAYING; + if (al_state==AL_PAUSED) snd->state=SND_STATE_PAUSED; + } }//sndupdate int32 func__sndcopy(int32 handle){ -if (new_error) return 0; -sndsetup(); -if (handle==0) return 0;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return 0;} -if (snd->internal){error(5); return 0;} -if (snd->type==2){ -if (snd->streamed){error(5); return 0;} -sndupdate(snd); -static snd_sequence_struct *seq; seq=snd->seq; -//increment seq references -seq->references++; -static snd_struct *snd_source; snd_source=snd; -//create new snd handle -static int32 handle; handle=list_add(snd_handles); -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -//import all data -memcpy (snd,snd_source,sizeof(snd_struct)); -//adjust data -snd->al_seq_buffer=0;//no buffer -snd->al_seq_source=0;//no source -snd->volume_update=1; -snd->state=0; -return handle; -}//2 -error(5); return 0; + if (new_error) return 0; + sndsetup(); + if (handle==0) return 0;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return 0;} + if (snd->internal){error(5); return 0;} + if (snd->type==2){ + if (snd->streamed){error(5); return 0;} + sndupdate(snd); + static snd_sequence_struct *seq; seq=snd->seq; + //increment seq references + seq->references++; + static snd_struct *snd_source; snd_source=snd; + //create new snd handle + static int32 handle; handle=list_add(snd_handles); + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + //import all data + memcpy (snd,snd_source,sizeof(snd_struct)); + //adjust data + snd->al_seq_buffer=0;//no buffer + snd->al_seq_source=0;//no source + snd->volume_update=1; + snd->state=0; + return handle; + }//2 + error(5); return 0; }//sndcopy @@ -918,377 +918,377 @@ error(5); return 0; int32 sub__sndvol_error=0; void sub__sndvol(int32 handle,float volume){ -if (new_error) return; -sndsetup(); -sub__sndvol_error=0; -if (handle==0) return;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -sub__sndvol_error=1; -if (!snd){error(5); return;} -if (snd->internal){error(5); return;} -if (!(snd->capability&SND_CAPABILITY_VOL)){error(5); return;} -snd->volume=volume; snd->volume_update=1; -sndupdate(snd); -sub__sndvol_error=0; + if (new_error) return; + sndsetup(); + sub__sndvol_error=0; + if (handle==0) return;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + sub__sndvol_error=1; + if (!snd){error(5); return;} + if (snd->internal){error(5); return;} + if (!(snd->capability&SND_CAPABILITY_VOL)){error(5); return;} + snd->volume=volume; snd->volume_update=1; + sndupdate(snd); + sub__sndvol_error=0; } void sub__sndpause(int32 handle){ -if (new_error) return; -sndsetup(); -if (handle==0) return;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return;} -if (!(snd->capability&SND_CAPABILITY_PAUSE)){error(5); return;} -if (snd->internal){error(5); return;} -if (snd->type==2){ -static snd_sequence_struct *seq; seq=snd->seq; -sndupdate(snd); -if (snd->al_seq_source){ -if (snd->state==SND_STATE_PLAYING){ -alSourcePause(snd->al_seq_source); snd->state=SND_STATE_PAUSED; -if (snd->limit_state==2) snd->limit_state=0;//disable limit -} -}//source -return; -}//2 -error(5); + if (new_error) return; + sndsetup(); + if (handle==0) return;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return;} + if (!(snd->capability&SND_CAPABILITY_PAUSE)){error(5); return;} + if (snd->internal){error(5); return;} + if (snd->type==2){ + static snd_sequence_struct *seq; seq=snd->seq; + sndupdate(snd); + if (snd->al_seq_source){ + if (snd->state==SND_STATE_PLAYING){ + alSourcePause(snd->al_seq_source); snd->state=SND_STATE_PAUSED; + if (snd->limit_state==2) snd->limit_state=0;//disable limit + } + }//source + return; + }//2 + error(5); }//sndpause void sub__sndstop(int32 handle){ -if (new_error) return; -sndsetup(); -if (handle==0) return;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return;} -if (snd->internal){error(5); return;} -if (snd->type==2){ -static snd_sequence_struct *seq; seq=snd->seq; -sndupdate(snd); -if (snd->al_seq_source){ -if (snd->state!=SND_STATE_STOPPED){ -alSourceStop(snd->al_seq_source); snd->state=SND_STATE_STOPPED; -if (snd->limit_state==2) snd->limit_state=0;//disable limit -} -}//source -return; -}//2 -error(5); + if (new_error) return; + sndsetup(); + if (handle==0) return;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return;} + if (snd->internal){error(5); return;} + if (snd->type==2){ + static snd_sequence_struct *seq; seq=snd->seq; + sndupdate(snd); + if (snd->al_seq_source){ + if (snd->state!=SND_STATE_STOPPED){ + alSourceStop(snd->al_seq_source); snd->state=SND_STATE_STOPPED; + if (snd->limit_state==2) snd->limit_state=0;//disable limit + } + }//source + return; + }//2 + error(5); }//sndstop void snd_seq_buildmono(snd_sequence_struct* seq){ -if (!seq->data_mono){ -//we know: its stereo, its 16-bit -//our plan: average out every 2nd sample -static int32 samples; -samples=seq->data_stereo_size/4; -static int16 *src; -static int16 *dst; -src=(int16*)seq->data_stereo; -dst=(int16*)malloc(samples*2); -static int32 i; -for (i=0;idata_mono=(uint8*)dst; -seq->data_mono_size=samples*2; -}//no mono + if (!seq->data_mono){ + //we know: its stereo, its 16-bit + //our plan: average out every 2nd sample + static int32 samples; + samples=seq->data_stereo_size/4; + static int16 *src; + static int16 *dst; + src=(int16*)seq->data_stereo; + dst=(int16*)malloc(samples*2); + static int32 i; + for (i=0;idata_mono=(uint8*)dst; + seq->data_mono_size=samples*2; + }//no mono }//snd_seq_buildmono int32 sndplay_loop=0; void sub__sndplay(int32 handle){ -if (new_error) return; -sndsetup(); -if (handle==0) return;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return;} -if (!snd_allow_internal){ - if (snd->internal){error(5); return;} -} -if (snd->type==2){ -static snd_sequence_struct *seq; seq=snd->seq; + if (new_error) return; + sndsetup(); + if (handle==0) return;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return;} + if (!snd_allow_internal){ + if (snd->internal){error(5); return;} + } + if (snd->type==2){ + static snd_sequence_struct *seq; seq=snd->seq; switch_to_mono: -if (!snd->al_seq_buffer){ - alGenBuffers(1,&snd->al_seq_buffer); - snd->al_seq_freq=snd_frequency; + if (!snd->al_seq_buffer){ + alGenBuffers(1,&snd->al_seq_buffer); + snd->al_seq_freq=snd_frequency; - static int32 mono; - mono=0; - if (!seq->data_stereo) mono=1; - if (seq->data_mono) mono=1; - if (mono){ - snd->al_seq_data=(ALvoid*)seq->data_mono; - snd->al_seq_size=seq->data_mono_size; - snd->al_seq_format=AL_FORMAT_MONO16; - }else{ - snd->al_seq_data=(ALvoid*)seq->data_stereo; - snd->al_seq_size=seq->data_stereo_size; - snd->al_seq_format=AL_FORMAT_STEREO16; - } - /* ref: - #define AL_FORMAT_MONO8 0x1100 - #define AL_FORMAT_MONO16 0x1101 - #define AL_FORMAT_STEREO8 0x1102 - #define AL_FORMAT_STEREO16 0x1103 - */ - alBufferData(snd->al_seq_buffer,snd->al_seq_format,snd->al_seq_data,snd->al_seq_size,snd->al_seq_freq); -} -if (!snd->al_seq_source){ - alGenSources(1,&snd->al_seq_source); + static int32 mono; + mono=0; + if (!seq->data_stereo) mono=1; + if (seq->data_mono) mono=1; + if (mono){ + snd->al_seq_data=(ALvoid*)seq->data_mono; + snd->al_seq_size=seq->data_mono_size; + snd->al_seq_format=AL_FORMAT_MONO16; + }else{ + snd->al_seq_data=(ALvoid*)seq->data_stereo; + snd->al_seq_size=seq->data_stereo_size; + snd->al_seq_format=AL_FORMAT_STEREO16; + } + /* ref: +#define AL_FORMAT_MONO8 0x1100 +#define AL_FORMAT_MONO16 0x1101 +#define AL_FORMAT_STEREO8 0x1102 +#define AL_FORMAT_STEREO16 0x1103 + */ + alBufferData(snd->al_seq_buffer,snd->al_seq_format,snd->al_seq_data,snd->al_seq_size,snd->al_seq_freq); + } + if (!snd->al_seq_source){ + alGenSources(1,&snd->al_seq_source); - alSourcef(snd->al_seq_source,AL_REFERENCE_DISTANCE,0.01); - alSourcef(snd->al_seq_source,AL_MAX_DISTANCE,10); - alSourcef(snd->al_seq_source,AL_ROLLOFF_FACTOR,1); + alSourcef(snd->al_seq_source,AL_REFERENCE_DISTANCE,0.01); + alSourcef(snd->al_seq_source,AL_MAX_DISTANCE,10); + alSourcef(snd->al_seq_source,AL_ROLLOFF_FACTOR,1); - alSourcei(snd->al_seq_source,AL_BUFFER,snd->al_seq_buffer); -} + alSourcei(snd->al_seq_source,AL_BUFFER,snd->al_seq_buffer); + } -sndupdate_dont_free_resources=1; -sndupdate(snd); -if (snd->state==SND_STATE_PLAYING){ - sub__sndstop(handle); - sndupdate(snd); -} -sndupdate_dont_free_resources=0; + sndupdate_dont_free_resources=1; + sndupdate(snd); + if (snd->state==SND_STATE_PLAYING){ + sub__sndstop(handle); + sndupdate(snd); + } + sndupdate_dont_free_resources=0; -if (snd->state==SND_STATE_STOPPED){ -if (snd->use_mono){ -if (!seq->data_mono){//does a mono version exist? -snd_seq_buildmono(seq);//create a mono version -sndupdate(snd);//trigger destruction of current buffer, source and the update of states -goto switch_to_mono; -}//create mono -}//needs mono -}//stopped + if (snd->state==SND_STATE_STOPPED){ + if (snd->use_mono){ + if (!seq->data_mono){//does a mono version exist? + snd_seq_buildmono(seq);//create a mono version + sndupdate(snd);//trigger destruction of current buffer, source and the update of states + goto switch_to_mono; + }//create mono + }//needs mono + }//stopped -if (sndplay_loop){ - alSourcei(snd->al_seq_source, AL_LOOPING, AL_TRUE); -}else{ - alSourcei(snd->al_seq_source, AL_LOOPING, AL_FALSE); -} -alSourcePlay(snd->al_seq_source); snd->state=SND_STATE_PLAYING; + if (sndplay_loop){ + alSourcei(snd->al_seq_source, AL_LOOPING, AL_TRUE); + }else{ + alSourcei(snd->al_seq_source, AL_LOOPING, AL_FALSE); + } + alSourcePlay(snd->al_seq_source); snd->state=SND_STATE_PLAYING; -if (snd->limit_state==2) snd->limit_state=0;//disable limit -if (snd->limit_state==1){ - snd->limit_stop_point=GetTicks()+(snd->limit_duration*1000.0); - snd->limit_state=2; -} + if (snd->limit_state==2) snd->limit_state=0;//disable limit + if (snd->limit_state==1){ + snd->limit_stop_point=GetTicks()+(snd->limit_duration*1000.0); + snd->limit_state=2; + } -return; -}//2 -error(5); + return; + }//2 + error(5); }//sndplay void sub__sndloop(int32 handle){ -sndplay_loop=1; -sub__sndplay(handle);//call SNDPLAY with loop option set -sndplay_loop=0; + sndplay_loop=1; + sub__sndplay(handle);//call SNDPLAY with loop option set + sndplay_loop=0; }//sndloop int32 func__sndpaused(int32 handle){ -if (new_error) return 0; -sndsetup(); -if (handle==0) return 0;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return 0;} -if (snd->internal){error(5); return 0;} -sndupdate(snd); -if (snd->state==SND_STATE_PAUSED) return -1; -return 0; + if (new_error) return 0; + sndsetup(); + if (handle==0) return 0;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return 0;} + if (snd->internal){error(5); return 0;} + sndupdate(snd); + if (snd->state==SND_STATE_PAUSED) return -1; + return 0; }//sndpaused int32 func__sndplaying(int32 handle){ -if (new_error) return 0; -sndsetup(); -if (handle==0) return 0;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return 0;} -if (snd->internal){error(5); return 0;} -sndupdate(snd); -if (snd->state==SND_STATE_PLAYING) return -1; -return 0; + if (new_error) return 0; + sndsetup(); + if (handle==0) return 0;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return 0;} + if (snd->internal){error(5); return 0;} + sndupdate(snd); + if (snd->state==SND_STATE_PLAYING) return -1; + return 0; }//func__sndplaying double func__sndlen(int32 handle){ -if (new_error) return 0; -sndsetup(); -if (handle==0) return 0;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return 0;} -if (!(snd->capability&SND_CAPABILITY_LEN)){error(5); return 0;} -if (snd->internal){error(5); return 0;} -if (snd->type==2){ -static snd_sequence_struct *seq; seq=snd->seq; -static int32 samples; samples=seq->data_size/seq->channels/(seq->bits_per_sample/8); -static double seconds; seconds=((double)samples)/((double)seq->sample_rate); -return seconds; -}//2 -error(5); return 0; + if (new_error) return 0; + sndsetup(); + if (handle==0) return 0;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return 0;} + if (!(snd->capability&SND_CAPABILITY_LEN)){error(5); return 0;} + if (snd->internal){error(5); return 0;} + if (snd->type==2){ + static snd_sequence_struct *seq; seq=snd->seq; + static int32 samples; samples=seq->data_size/seq->channels/(seq->bits_per_sample/8); + static double seconds; seconds=((double)samples)/((double)seq->sample_rate); + return seconds; + }//2 + error(5); return 0; } void sub__sndbal(int32 handle,double x,double y,double z,int32 passed){ -//note: any optional parameter not passed is assumed to be 0 (which is what NULL equates to) -if (new_error) return; -sndsetup(); -if (handle==0) return;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return;} -if (!(snd->capability&SND_CAPABILITY_VOL)){error(5); return;} -if (snd->internal){error(5); return;} -if (snd->type==2){ -static snd_sequence_struct *seq; seq=snd->seq; -if (passed&(2+4)){ -if ((y==0)&&(z==0)) z=0.001;//trigger 3D sound placement -} -snd->bal_x=x; snd->bal_y=y; snd->bal_z=z; snd->bal_update=1; -sndupdate(snd); -}//2 -//... + //note: any optional parameter not passed is assumed to be 0 (which is what NULL equates to) + if (new_error) return; + sndsetup(); + if (handle==0) return;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return;} + if (!(snd->capability&SND_CAPABILITY_VOL)){error(5); return;} + if (snd->internal){error(5); return;} + if (snd->type==2){ + static snd_sequence_struct *seq; seq=snd->seq; + if (passed&(2+4)){ + if ((y==0)&&(z==0)) z=0.001;//trigger 3D sound placement + } + snd->bal_x=x; snd->bal_y=y; snd->bal_z=z; snd->bal_update=1; + sndupdate(snd); + }//2 + //... }//sndbal double func__sndgetpos(int32 handle){ -if (new_error) return 0; -sndsetup(); -if (handle==0) return 0;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return 0;} -if (snd->internal){error(5); return 0;} -if (snd->type==2){ -if (snd->al_seq_source){ -static float seconds; -alGetSourcef(snd->al_seq_source,AL_SEC_OFFSET,&seconds); -return seconds; -} -return 0; -} -error(5); return 0; + if (new_error) return 0; + sndsetup(); + if (handle==0) return 0;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return 0;} + if (snd->internal){error(5); return 0;} + if (snd->type==2){ + if (snd->al_seq_source){ + static float seconds; + alGetSourcef(snd->al_seq_source,AL_SEC_OFFSET,&seconds); + return seconds; + } + return 0; + } + error(5); return 0; }//getpos void sub__sndsetpos(int32 handle,double seconds){ -if (new_error) return; -if (seconds<0){error(5); return;} -sndsetup(); -if (handle==0) return;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return;} -if (!(snd->capability&SND_CAPABILITY_SETPOS)){error(5); return;} -if (snd->internal){error(5); return;} -if (snd->type==2){ -snd->setpos=seconds; -snd->setpos_update=1; -sndupdate(snd); -return; -} -error(5); + if (new_error) return; + if (seconds<0){error(5); return;} + sndsetup(); + if (handle==0) return;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return;} + if (!(snd->capability&SND_CAPABILITY_SETPOS)){error(5); return;} + if (snd->internal){error(5); return;} + if (snd->type==2){ + snd->setpos=seconds; + snd->setpos_update=1; + sndupdate(snd); + return; + } + error(5); }//setpos void sub__sndlimit(int32 handle,double limit){ -if (new_error) return; -if (limit<0){error(5); return;} -sndsetup(); -if (handle==0) return;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return;} -if (snd->internal){error(5); return;} -if (snd->type==2){ -if (limit==0){snd->limit_state=0; return;} -sndupdate(snd); -if (snd->state==SND_STATE_PLAYING){ - //begin count immediately - snd->limit_stop_point=GetTicks()+(limit*1000.0); - snd->limit_state=2; -}else{ - //begin after play is called - snd->limit_duration=limit; - snd->limit_state=1; -} -return; -} -error(5); return; + if (new_error) return; + if (limit<0){error(5); return;} + sndsetup(); + if (handle==0) return;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return;} + if (snd->internal){error(5); return;} + if (snd->type==2){ + if (limit==0){snd->limit_state=0; return;} + sndupdate(snd); + if (snd->state==SND_STATE_PLAYING){ + //begin count immediately + snd->limit_stop_point=GetTicks()+(limit*1000.0); + snd->limit_state=2; + }else{ + //begin after play is called + snd->limit_duration=limit; + snd->limit_state=1; + } + return; + } + error(5); return; } //note: this is an internal command void sndclose_now(int32 handle){ -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (snd->streamed) snd_stream_handle=0; + if (snd->streamed) snd_stream_handle=0; -if (snd->type==2){ - //remove OpenAL content - if (snd->al_seq_source){ - alDeleteSources(1,&snd->al_seq_source); snd->al_seq_source=0; - alDeleteBuffers(1,&snd->al_seq_buffer); snd->al_seq_buffer=0; - } - static snd_sequence_struct *seq; seq=snd->seq; - //remove sound handle - list_remove(snd_handles,handle); + if (snd->type==2){ + //remove OpenAL content + if (snd->al_seq_source){ + alDeleteSources(1,&snd->al_seq_source); snd->al_seq_source=0; + alDeleteBuffers(1,&snd->al_seq_buffer); snd->al_seq_buffer=0; + } + static snd_sequence_struct *seq; seq=snd->seq; + //remove sound handle + list_remove(snd_handles,handle); - //remove seq - if (seq->references>1){ - seq->references--; - }else{ - free(seq->data); - if (seq->data_stereo){ - if (seq->data_stereo!=seq->data) free(seq->data_stereo); - } - if (seq->data_mono){ - if (seq->data_mono!=seq->data) free(seq->data_mono); - } - static int32 seq_handle; seq_handle=list_get_index(snd_sequences,seq); - list_remove(snd_sequences,seq_handle); - } -}//2 + //remove seq + if (seq->references>1){ + seq->references--; + }else{ + free(seq->data); + if (seq->data_stereo){ + if (seq->data_stereo!=seq->data) free(seq->data_stereo); + } + if (seq->data_mono){ + if (seq->data_mono!=seq->data) free(seq->data_mono); + } + static int32 seq_handle; seq_handle=list_get_index(snd_sequences,seq); + list_remove(snd_sequences,seq_handle); + } + }//2 -if (snd->type==1){ - list_remove(snd_handles,handle); -} + if (snd->type==1){ + list_remove(snd_handles,handle); + } }//sndclose_now void sub__sndclose(int32 handle){ -if (new_error) return; -sndsetup(); -if (handle==0) return;//default response -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd){error(5); return;} -if (snd->internal){error(5); return;} -sndupdate(snd); -snd->internal=1;//switch to internal, no more commands related to this sound can be accepted -if (snd->type==2){ - if (snd->state==SND_STATE_PLAYING){ - snd->close=1;//close when finished playing - }else{ - sndclose_now(handle); - } - return; -} -snd->close=1;//raw -snd->raw_close_time=GetTicks(); + if (new_error) return; + sndsetup(); + if (handle==0) return;//default response + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd){error(5); return;} + if (snd->internal){error(5); return;} + sndupdate(snd); + snd->internal=1;//switch to internal, no more commands related to this sound can be accepted + if (snd->type==2){ + if (snd->state==SND_STATE_PLAYING){ + snd->close=1;//close when finished playing + }else{ + sndclose_now(handle); + } + return; + } + snd->close=1;//raw + snd->raw_close_time=GetTicks(); }//sndclose //"macros" void sub__sndplaycopy(int32 handle,double volume,int32 passed){ -if (new_error) return; -sndsetup(); -int32 handle2; -handle2=func__sndcopy(handle); -if (!handle2) return;//an error has already happened -if (passed){ -sub__sndvol(handle2,volume); -if (sub__sndvol_error){ -sub__sndclose(handle2); -return; -} -} -sub__sndplay(handle2); -sub__sndclose(handle2); + if (new_error) return; + sndsetup(); + int32 handle2; + handle2=func__sndcopy(handle); + if (!handle2) return;//an error has already happened + if (passed){ + sub__sndvol(handle2,volume); + if (sub__sndvol_error){ + sub__sndclose(handle2); + return; + } + } + sub__sndplay(handle2); + sub__sndclose(handle2); } @@ -1297,560 +1297,560 @@ sub__sndclose(handle2); //uint8 *soundwavesilence(double length,uint8 *data); int32 func_play(int32 ignore){ -return 0; + return 0; } /* Formats: A[#|+|-][0-64] - 0-64 is like temp. Lnumber, 0 is whatever the current default is -*/ +0-64 is like temp. Lnumber, 0 is whatever the current default is + */ void sub_play(qbs *str){ -sndsetup(); -static uint8 *b,*wave,*wave2,*wave3; -static double d; -static int32 i,bytes_left,a,x,x2,x3,x4,x5,wave_bytes,wave_base; -static int32 o=4; -static double t=120;//quarter notes per minute (120/60=2 per second) -static double l=4; -static double pause=1.0/8.0;//ML 0.0, MN 1.0/8.0, MS 1.0/4.0 -static double length,length2;//derived from l and t -static double frequency; -static double mb=0; -static double v=50; + sndsetup(); + static uint8 *b,*wave,*wave2,*wave3; + static double d; + static int32 i,bytes_left,a,x,x2,x3,x4,x5,wave_bytes,wave_base; + static int32 o=4; + static double t=120;//quarter notes per minute (120/60=2 per second) + static double l=4; + static double pause=1.0/8.0;//ML 0.0, MN 1.0/8.0, MS 1.0/4.0 + static double length,length2;//derived from l and t + static double frequency; + static double mb=0; + static double v=50; -static int32 n;//the semitone-intervaled note to be played -static int32 n_changed;//+,#,- applied? -static int64 number; -static int32 number_entered; -static int32 followup;//1=play note -static int32 playit; -static uint32 handle=NULL; -static int32 fullstops=0; -b=str->chr; -bytes_left=str->len; -wave=NULL; -wave_bytes=0; -n_changed=0; -n=0; -number_entered=0; -number=0; -followup=0; -length=1.0/(t/60.0)*(4.0/l); -playit=0; -wave_base=0;//point at which new sounds will be inserted + static int32 n;//the semitone-intervaled note to be played + static int32 n_changed;//+,#,- applied? + static int64 number; + static int32 number_entered; + static int32 followup;//1=play note + static int32 playit; + static uint32 handle=NULL; + static int32 fullstops=0; + b=str->chr; + bytes_left=str->len; + wave=NULL; + wave_bytes=0; + n_changed=0; + n=0; + number_entered=0; + number=0; + followup=0; + length=1.0/(t/60.0)*(4.0/l); + playit=0; + wave_base=0;//point at which new sounds will be inserted next_byte: -if ((bytes_left--)||followup){ + if ((bytes_left--)||followup){ -if (bytes_left<0){i=32; goto follow_up;} + if (bytes_left<0){i=32; goto follow_up;} -i=*b++; -if (i==32) goto next_byte; -if (i>=97&&i<=122) a=i-32; else a=i; + i=*b++; + if (i==32) goto next_byte; + if (i>=97&&i<=122) a=i-32; else a=i; -if (i==61){//= (+VARPTR$) -if (fullstops){error(5); return;} -if (number_entered){error(5); return;} -number_entered=2; -//VARPTR$ reference -/* -'BYTE=1 -'INTEGER=2 -'STRING=3 SUB-STRINGS must use "X"+VARPTR$(string$) -'SINGLE=4 -'INT64=5 -'FLOAT=6 -'DOUBLE=8 -'LONG=20 -'BIT=64+n -*/ -if (bytes_left<3){error(5); return;} -i=*b++; bytes_left--;//read type byte -x=*(uint16*)b; b+=2; bytes_left-=2;//read offset within DBLOCK -//note: allowable _BIT type variables in VARPTR$ are all at a byte offset and are all -// padded until the next byte -d=0; -switch(i){ -case 1: -d=*(char*)(dblock+x); -break; -case (1+128): -d=*(uint8*)(dblock+x); -break; -case 2: -d=*(int16*)(dblock+x); -break; -case (2+128): -d=*(uint16*)(dblock+x); -break; -case 4: -d=*(float*)(dblock+x); -break; -case 5: -d=*(int64*)(dblock+x); -break; -case (5+128): -d=*(int64*)(dblock+x); //unsigned conversion is unsupported! -break; -case 6: -d=*(long double*)(dblock+x); -break; -case 8: -d=*(double*)(dblock+x); -break; -case 20: -d=*(int32*)(dblock+x); -break; -case (20+128): -d=*(uint32*)(dblock+x); -break; -default: -//bit type? -if ((i&64)==0){error(5); return;} -x2=i&63; -if (x2>56){error(5); return;}//valid number of bits? -//create a mask -static int64 i64num,mask,i64x; -mask=(((int64)1)<2147483647.0||d<-2147483648.0){error(5); return;}//out of range value! -number=qbr_double_to_long(d); -goto next_byte; -} + if (i==61){//= (+VARPTR$) + if (fullstops){error(5); return;} + if (number_entered){error(5); return;} + number_entered=2; + //VARPTR$ reference + /* + 'BYTE=1 + 'INTEGER=2 + 'STRING=3 SUB-STRINGS must use "X"+VARPTR$(string$) + 'SINGLE=4 + 'INT64=5 + 'FLOAT=6 + 'DOUBLE=8 + 'LONG=20 + 'BIT=64+n + */ + if (bytes_left<3){error(5); return;} + i=*b++; bytes_left--;//read type byte + x=*(uint16*)b; b+=2; bytes_left-=2;//read offset within DBLOCK + //note: allowable _BIT type variables in VARPTR$ are all at a byte offset and are all + // padded until the next byte + d=0; + switch(i){ + case 1: + d=*(char*)(dblock+x); + break; + case (1+128): + d=*(uint8*)(dblock+x); + break; + case 2: + d=*(int16*)(dblock+x); + break; + case (2+128): + d=*(uint16*)(dblock+x); + break; + case 4: + d=*(float*)(dblock+x); + break; + case 5: + d=*(int64*)(dblock+x); + break; + case (5+128): + d=*(int64*)(dblock+x); //unsigned conversion is unsupported! + break; + case 6: + d=*(long double*)(dblock+x); + break; + case 8: + d=*(double*)(dblock+x); + break; + case 20: + d=*(int32*)(dblock+x); + break; + case (20+128): + d=*(uint32*)(dblock+x); + break; + default: + //bit type? + if ((i&64)==0){error(5); return;} + x2=i&63; + if (x2>56){error(5); return;}//valid number of bits? + //create a mask + static int64 i64num,mask,i64x; + mask=(((int64)1)<2147483647.0||d<-2147483648.0){error(5); return;}//out of range value! + number=qbr_double_to_long(d); + goto next_byte; + } -//read in a number -if ((i>=48)&&(i<=57)){ -if (fullstops||(number_entered==2)){error(5); return;} -if (!number_entered){number=0; number_entered=1;} -number=number*10+i-48; -goto next_byte; -} + //read in a number + if ((i>=48)&&(i<=57)){ + if (fullstops||(number_entered==2)){error(5); return;} + if (!number_entered){number=0; number_entered=1;} + number=number*10+i-48; + goto next_byte; + } -//read fullstops -if (i==46){ -if (followup!=7&&followup!=1&&followup!=4){error(5); return;} -fullstops++; -goto next_byte; -} + //read fullstops + if (i==46){ + if (followup!=7&&followup!=1&&followup!=4){error(5); return;} + fullstops++; + goto next_byte; + } follow_up: -if (followup==8){//V... -if (!number_entered){error(5); return;} -number_entered=0; -if (number>100){error(5); return;} -v=number; -followup=0; if (bytes_left<0) goto done; -}//8 + if (followup==8){//V... + if (!number_entered){error(5); return;} + number_entered=0; + if (number>100){error(5); return;} + v=number; + followup=0; if (bytes_left<0) goto done; + }//8 -if (followup==7){//P... -if (number_entered){ -number_entered=0; -if (number<1||number>64){error(5); return;} -length2=1.0/(t/60.0)*(4.0/((double)number)); -}else{ -length2=length; -} -d=length2; for (x=1;x<=fullstops;x++){d/=2.0; length2=length2+d;} fullstops=0; + if (followup==7){//P... + if (number_entered){ + number_entered=0; + if (number<1||number>64){error(5); return;} + length2=1.0/(t/60.0)*(4.0/((double)number)); + }else{ + length2=length; + } + d=length2; for (x=1;x<=fullstops;x++){d/=2.0; length2=length2+d;} fullstops=0; -soundwave_bytes=wavesize(length2); -if (!wave){ - //create buffer - wave=(uint8*)calloc(soundwave_bytes,1); wave_bytes=soundwave_bytes; - wave_base=0; -}else{ - //increase buffer? - if ((wave_base+soundwave_bytes)>wave_bytes){ - wave=(uint8*)realloc(wave,wave_base+soundwave_bytes); - memset(wave+wave_base,0,wave_base+soundwave_bytes-wave_bytes); - wave_bytes=wave_base+soundwave_bytes; - } -} -if (i!=44){ -wave_base+=soundwave_bytes; -} + soundwave_bytes=wavesize(length2); + if (!wave){ + //create buffer + wave=(uint8*)calloc(soundwave_bytes,1); wave_bytes=soundwave_bytes; + wave_base=0; + }else{ + //increase buffer? + if ((wave_base+soundwave_bytes)>wave_bytes){ + wave=(uint8*)realloc(wave,wave_base+soundwave_bytes); + memset(wave+wave_base,0,wave_base+soundwave_bytes-wave_bytes); + wave_bytes=wave_base+soundwave_bytes; + } + } + if (i!=44){ + wave_base+=soundwave_bytes; + } -playit=1; -followup=0; -if (i==44) goto next_byte; -if (bytes_left<0) goto done; -}//7 + playit=1; + followup=0; + if (i==44) goto next_byte; + if (bytes_left<0) goto done; + }//7 -if (followup==6){//T... -if (!number_entered){error(5); return;} -number_entered=0; -if (number<32||number>255){number=120;} -t=number; -length=1.0/(t/60.0)*(4.0/l); -followup=0; if (bytes_left<0) goto done; -}//6 + if (followup==6){//T... + if (!number_entered){error(5); return;} + number_entered=0; + if (number<32||number>255){number=120;} + t=number; + length=1.0/(t/60.0)*(4.0/l); + followup=0; if (bytes_left<0) goto done; + }//6 -if (followup==5){//M... -if (number_entered){error(5); return;} -switch(a){ -case 76://L -pause=0; -break; -case 78://N -pause=1.0/8.0; -break; -case 83://S -pause=1.0/4.0; -break; + if (followup==5){//M... + if (number_entered){error(5); return;} + switch(a){ + case 76://L + pause=0; + break; + case 78://N + pause=1.0/8.0; + break; + case 83://S + pause=1.0/4.0; + break; -case 66://MB -if (!mb){ - mb=1; - if (playit){ - playit=0; - qb64_internal_sndraw(wave,wave_bytes,1); - } - wave=NULL; -} -break; -case 70://MF -if (mb){ -mb=0; -//preceding MB content incorporated into MF block -} -break; -default: -error(5); return; -} -followup=0; goto next_byte; -}//5 + case 66://MB + if (!mb){ + mb=1; + if (playit){ + playit=0; + qb64_internal_sndraw(wave,wave_bytes,1); + } + wave=NULL; + } + break; + case 70://MF + if (mb){ + mb=0; + //preceding MB content incorporated into MF block + } + break; + default: + error(5); return; + } + followup=0; goto next_byte; + }//5 -if (followup==4){//N... -if (!number_entered){error(5); return;} -number_entered=0; -if (number>84){error(5); return;} -n=-33+number; -goto followup1; -followup=0; if (bytes_left<0) goto done; -}//4 + if (followup==4){//N... + if (!number_entered){error(5); return;} + number_entered=0; + if (number>84){error(5); return;} + n=-33+number; + goto followup1; + followup=0; if (bytes_left<0) goto done; + }//4 -if (followup==3){//O... -if (!number_entered){error(5); return;} -number_entered=0; -if (number>6){error(5); return;} -o=number; -followup=0; if (bytes_left<0) goto done; -}//3 + if (followup==3){//O... + if (!number_entered){error(5); return;} + number_entered=0; + if (number>6){error(5); return;} + o=number; + followup=0; if (bytes_left<0) goto done; + }//3 -if (followup==2){//L... -if (!number_entered){error(5); return;} -number_entered=0; -if (number<1||number>64){error(5); return;} -l=number; -length=1.0/(t/60.0)*(4.0/l); -followup=0; if (bytes_left<0) goto done; -}//2 + if (followup==2){//L... + if (!number_entered){error(5); return;} + number_entered=0; + if (number<1||number>64){error(5); return;} + l=number; + length=1.0/(t/60.0)*(4.0/l); + followup=0; if (bytes_left<0) goto done; + }//2 -if (followup==1){//A-G... -if (i==45){//- - if (n_changed||number_entered){error(5); return;} - n_changed=1; n--; - goto next_byte; -} -if (i==43||i==35){//+,# - if (n_changed||number_entered){error(5); return;} - n_changed=1; n++; -goto next_byte; -} + if (followup==1){//A-G... + if (i==45){//- + if (n_changed||number_entered){error(5); return;} + n_changed=1; n--; + goto next_byte; + } + if (i==43||i==35){//+,# + if (n_changed||number_entered){error(5); return;} + n_changed=1; n++; + goto next_byte; + } followup1: -if (number_entered){ - number_entered=0; - if (number<0||number>64){error(5); return;} - if (!number) length2=length; else length2=1.0/(t/60.0)*(4.0/((double)number)); -}else{ - length2=length; -}//number_entered -d=length2; for (x=1;x<=fullstops;x++){d/=2.0; length2=length2+d;} fullstops=0; -//frequency=(2^(note/12))*440 -frequency=pow(2.0,((double)n)/12.0)*440.0; + if (number_entered){ + number_entered=0; + if (number<0||number>64){error(5); return;} + if (!number) length2=length; else length2=1.0/(t/60.0)*(4.0/((double)number)); + }else{ + length2=length; + }//number_entered + d=length2; for (x=1;x<=fullstops;x++){d/=2.0; length2=length2+d;} fullstops=0; + //frequency=(2^(note/12))*440 + frequency=pow(2.0,((double)n)/12.0)*440.0; -//create wave -wave2=soundwave(frequency,length2*(1.0-pause),v/100.0,NULL,NULL); -if (pause>0){ -wave2=(uint8*)realloc(wave2,soundwave_bytes+wavesize(length2*pause)); -memset(wave2+soundwave_bytes,0,wavesize(length2*pause)); -soundwave_bytes+=wavesize(length2*pause); -} + //create wave + wave2=soundwave(frequency,length2*(1.0-pause),v/100.0,NULL,NULL); + if (pause>0){ + wave2=(uint8*)realloc(wave2,soundwave_bytes+wavesize(length2*pause)); + memset(wave2+soundwave_bytes,0,wavesize(length2*pause)); + soundwave_bytes+=wavesize(length2*pause); + } -if (!wave){ - //adopt buffer - wave=wave2; wave_bytes=soundwave_bytes; - wave_base=0; -}else{ - //mix required? - if (wave_base==wave_bytes) x=0; else x=1; - //increase buffer? - if ((wave_base+soundwave_bytes)>wave_bytes){ - wave=(uint8*)realloc(wave,wave_base+soundwave_bytes); - memset(wave+wave_base,0,wave_base+soundwave_bytes-wave_bytes); - wave_bytes=wave_base+soundwave_bytes; - } - //mix or copy - if (x){ - //mix - static int16 *sp,*sp2; - sp=(int16*)(wave+wave_base); - sp2=(int16*)wave2; - x2=soundwave_bytes/2; - for (x=0;x32767) x4=32767; - if (x4<-32767) x4=-32767; - *sp++=x4; - }//x - }else{ - //copy - memcpy(wave+wave_base,wave2,soundwave_bytes); - }//x - free(wave2); -} -if (i!=44){ -wave_base+=soundwave_bytes; -} + if (!wave){ + //adopt buffer + wave=wave2; wave_bytes=soundwave_bytes; + wave_base=0; + }else{ + //mix required? + if (wave_base==wave_bytes) x=0; else x=1; + //increase buffer? + if ((wave_base+soundwave_bytes)>wave_bytes){ + wave=(uint8*)realloc(wave,wave_base+soundwave_bytes); + memset(wave+wave_base,0,wave_base+soundwave_bytes-wave_bytes); + wave_bytes=wave_base+soundwave_bytes; + } + //mix or copy + if (x){ + //mix + static int16 *sp,*sp2; + sp=(int16*)(wave+wave_base); + sp2=(int16*)wave2; + x2=soundwave_bytes/2; + for (x=0;x32767) x4=32767; + if (x4<-32767) x4=-32767; + *sp++=x4; + }//x + }else{ + //copy + memcpy(wave+wave_base,wave2,soundwave_bytes); + }//x + free(wave2); + } + if (i!=44){ + wave_base+=soundwave_bytes; + } -playit=1; -n_changed=0; -followup=0; -if (i==44) goto next_byte; -if (bytes_left<0) goto done; -}//1 + playit=1; + n_changed=0; + followup=0; + if (i==44) goto next_byte; + if (bytes_left<0) goto done; + }//1 -if (a>=65&&a<=71){ -//modify a to represent a semitonal note (n) interval -switch(a){ -//[c][ ][d][ ][e][f][ ][g][ ][a][ ][b] -// 0 1 2 3 4 5 6 7 8 9 0 1 -case 65: n=9; break; -case 66: n=11; break; -case 67: n=0; break; -case 68: n=2; break; -case 69: n=4; break; -case 70: n=5; break; -case 71: n=7; break; -} -n=n+(o-2)*12-9; -followup=1; -goto next_byte; -}//a + if (a>=65&&a<=71){ + //modify a to represent a semitonal note (n) interval + switch(a){ + //[c][ ][d][ ][e][f][ ][g][ ][a][ ][b] + // 0 1 2 3 4 5 6 7 8 9 0 1 + case 65: n=9; break; + case 66: n=11; break; + case 67: n=0; break; + case 68: n=2; break; + case 69: n=4; break; + case 70: n=5; break; + case 71: n=7; break; + } + n=n+(o-2)*12-9; + followup=1; + goto next_byte; + }//a -if (a==76){//L -followup=2; -goto next_byte; -} + if (a==76){//L + followup=2; + goto next_byte; + } -if (a==77){//M -followup=5; -goto next_byte; -} + if (a==77){//M + followup=5; + goto next_byte; + } -if (a==78){//N -followup=4; -goto next_byte; -} + if (a==78){//N + followup=4; + goto next_byte; + } -if (a==79){//O -followup=3; -goto next_byte; -} + if (a==79){//O + followup=3; + goto next_byte; + } -if (a==84){//T -followup=6; -goto next_byte; -} + if (a==84){//T + followup=6; + goto next_byte; + } -if (a==60){//< -o--; if (o<0) o=0; -goto next_byte; -} + if (a==60){//< + o--; if (o<0) o=0; + goto next_byte; + } -if (a==62){//> -o++; if (o>6) o=6; -goto next_byte; -} + if (a==62){//> + o++; if (o>6) o=6; + goto next_byte; + } -if (a==80){//P -followup=7; -goto next_byte; -} + if (a==80){//P + followup=7; + goto next_byte; + } -if (a==86){//V -followup=8; -goto next_byte; -} + if (a==86){//V + followup=8; + goto next_byte; + } -error(5); return; -}//bytes_left + error(5); return; + }//bytes_left done: -if (number_entered||followup){error(5); return;}//unhandled data + if (number_entered||followup){error(5); return;}//unhandled data -if (playit){ - if (mb){ - qb64_internal_sndraw(wave,wave_bytes,0); - }else{ - qb64_internal_sndraw(wave,wave_bytes,1); - } -}//playit + if (playit){ + if (mb){ + qb64_internal_sndraw(wave,wave_bytes,0); + }else{ + qb64_internal_sndraw(wave,wave_bytes,1); + } + }//playit } int32 func__sndrate(){ -return snd_frequency; + return snd_frequency; } void qb64_generatesound(double f,double l,uint8 block){ -sndsetup(); -static uint8* data; -data=soundwave(f,l,1,0,0); -qb64_internal_sndraw(data,soundwave_bytes,block); + sndsetup(); + static uint8* data; + data=soundwave(f,l,1,0,0); + qb64_internal_sndraw(data,soundwave_bytes,block); } void qb64_internal_sndraw(uint8* data,int32 bytes,int32 block){//data required in 16bit stereo at native frequency, data is freed -sndsetup(); -static int32 i; -if (qb64_internal_sndraw_handle==0){ - qb64_internal_sndraw_handle=func__sndopenraw(); - qb64_internal_sndraw_prepad=1; -} + sndsetup(); + static int32 i; + if (qb64_internal_sndraw_handle==0){ + qb64_internal_sndraw_handle=func__sndopenraw(); + qb64_internal_sndraw_prepad=1; + } -int64 buffered_ms; -if (block){ - buffered_ms=func__sndrawlen(qb64_internal_sndraw_handle,1)*1000.0; - buffered_ms=((double)buffered_ms)*0.95;//take 95% of actual length to allow time for processing of new content - buffered_ms-=250;//allow for latency (call frequency and pre/post pad) - if (buffered_ms<0) buffered_ms=0; -} + int64 buffered_ms; + if (block){ + buffered_ms=func__sndrawlen(qb64_internal_sndraw_handle,1)*1000.0; + buffered_ms=((double)buffered_ms)*0.95;//take 95% of actual length to allow time for processing of new content + buffered_ms-=250;//allow for latency (call frequency and pre/post pad) + if (buffered_ms<0) buffered_ms=0; + } -if (qb64_internal_sndraw_prepad){ - qb64_internal_sndraw_prepad=0; - //pad initial buffer so that first sound is played immediately - static int32 snd_buffer_size_samples; - snd_buffer_size_samples=snd_buffer_size/2/2; - static int32 n; - n=snd_buffer_size_samples-(bytes/2/2); - if (n>0){ - for (i=0;i0){ + for (i=0;i0){ - sub__delay(((double)length_ms+(double)buffered_ms)/1000.0); - } -} + if (block){ + int64 length_ms; + length_ms=(((bytes/2/2)*1000)/snd_frequency);//length in ms + length_ms=((double)length_ms)*0.95;//take 95% of actual length to allow time for processing of new content + length_ms-=250;//allow for latency (call frequency and pre/post pad) + if (length_ms>0){ + sub__delay(((double)length_ms+(double)buffered_ms)/1000.0); + } + } } double func__sndrawlen(int32 handle,int32 passed){ -if (passed){ - if (handle==0) return 0; -}else{ - if (!snd_raw_channel) return 0; - handle=snd_raw_channel; -} -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd) goto error; -if (snd->internal) goto error; -if (snd->type!=1) goto error; -if (!snd->stream_buffer_start) return 0; -//count buffered source buffers -static int32 source_buffers; -source_buffers=0; -static int32 i; -i=snd->stream_buffer_start; -while(i!=snd->stream_buffer_next){ - source_buffers++; i++; if (i>snd->stream_buffer_last) i=1; -} -//count dest buffers -static int32 dest_buffers; -dest_buffers=0; -for (i=0;i<=3;i++){ - if (snd->al_buffer_state[i]==1) dest_buffers++; -} -return ((double)((dest_buffers+source_buffers)*(snd_buffer_size/2/2)))/(double)snd_frequency; + if (passed){ + if (handle==0) return 0; + }else{ + if (!snd_raw_channel) return 0; + handle=snd_raw_channel; + } + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd) goto error; + if (snd->internal) goto error; + if (snd->type!=1) goto error; + if (!snd->stream_buffer_start) return 0; + //count buffered source buffers + static int32 source_buffers; + source_buffers=0; + static int32 i; + i=snd->stream_buffer_start; + while(i!=snd->stream_buffer_next){ + source_buffers++; i++; if (i>snd->stream_buffer_last) i=1; + } + //count dest buffers + static int32 dest_buffers; + dest_buffers=0; + for (i=0;i<=3;i++){ + if (snd->al_buffer_state[i]==1) dest_buffers++; + } + return ((double)((dest_buffers+source_buffers)*(snd_buffer_size/2/2)))/(double)snd_frequency; error: -error(5); -return 0; + error(5); + return 0; } void sub__sndrawdone(int32 handle,int32 passed){ -if (passed){ - if (handle==0) return; -}else{ - if (!snd_raw_channel) return; - handle=snd_raw_channel; -} -static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); -if (!snd) goto error; -if (snd->internal) goto error; -if (snd->type!=1) goto error; -if (snd->buffer_size>0){//partial size -if (!qb64_sndraw_lock){//lock (or skip) -qb64_sndraw_lock=1; -while (snd->buffer_sizebuffer+snd->buffer_size)=0; - snd->buffer_size+=2; - *(int16*)(snd->buffer+snd->buffer_size)=0; - snd->buffer_size+=2; -} -//detach buffer - static uint8 *buffer; - buffer=snd->buffer; -//create new buffer - snd->buffer=(uint8*)calloc(snd_buffer_size,1); - snd->buffer_size=0; -//attach detached buffer to stream (or discard it) - static int32 p,p2; - p=snd->stream_buffer_next; p2=p+1; if (p2>snd->stream_buffer_last) p2=1; - if (p2==snd->stream_buffer_start){ - free(buffer); //all buffers are full! (quietly ignore this buffer) - }else{ - snd->stream_buffer[p]=(ptrszint)buffer; - snd->stream_buffer_next=p2; - if (!snd->stream_buffer_start) snd->stream_buffer_start=1; - } -//unlock - qb64_sndraw_lock=0; -}//lock (or skip) -}//partial size -return; + if (passed){ + if (handle==0) return; + }else{ + if (!snd_raw_channel) return; + handle=snd_raw_channel; + } + static snd_struct *snd; snd=(snd_struct*)list_get(snd_handles,handle); + if (!snd) goto error; + if (snd->internal) goto error; + if (snd->type!=1) goto error; + if (snd->buffer_size>0){//partial size + if (!qb64_sndraw_lock){//lock (or skip) + qb64_sndraw_lock=1; + while (snd->buffer_sizebuffer+snd->buffer_size)=0; + snd->buffer_size+=2; + *(int16*)(snd->buffer+snd->buffer_size)=0; + snd->buffer_size+=2; + } + //detach buffer + static uint8 *buffer; + buffer=snd->buffer; + //create new buffer + snd->buffer=(uint8*)calloc(snd_buffer_size,1); + snd->buffer_size=0; + //attach detached buffer to stream (or discard it) + static int32 p,p2; + p=snd->stream_buffer_next; p2=p+1; if (p2>snd->stream_buffer_last) p2=1; + if (p2==snd->stream_buffer_start){ + free(buffer); //all buffers are full! (quietly ignore this buffer) + }else{ + snd->stream_buffer[p]=(ptrszint)buffer; + snd->stream_buffer_next=p2; + if (!snd->stream_buffer_start) snd->stream_buffer_start=1; + } + //unlock + qb64_sndraw_lock=0; + }//lock (or skip) + }//partial size + return; error: -error(5); -return; + error(5); + return; } -#endif \ No newline at end of file +#endif