📄 audiolib_fx_fmod.c
字号:
/*--------------------------------------------------------------------- Function: FX_StopSound Halts playback of a specific voice---------------------------------------------------------------------*/int32_t FX_StopSound(int32_t handle){ FX_SimulateCallbacks(); FSOUND_StopSound(handle); if (handle>=0 && handle<FX_NumVoices) chstatesa[handle] = chstatesb[handle] = 0; // no callback for you! FX_SetErrorCode(FX_Ok); return FX_Ok;}/*--------------------------------------------------------------------- Function: FX_StopAllSounds Halts playback of all sounds.---------------------------------------------------------------------*/int32_t FX_StopAllSounds(void){ FX_SimulateCallbacks(); FSOUND_StopSound(FSOUND_ALL); memset(chstates, 0, FX_NumVoices*2); // no callbacks for any of you! FX_SetErrorCode(FX_Ok); return FX_Ok;}/*--------------------------------------------------------------------- Function: FX_Play*Sound Internal function to load a sound file and play it, returning the channel number it played on.---------------------------------------------------------------------*/int32_t FX_PlayLoopedSound( int32_t pitchoffset, int32_t vol, uint32_t num){ int32_t chan; FX_SimulateCallbacks(); if (!FX_Samples[num]) return -1; chan = FSOUND_PlaySoundEx(FSOUND_FREE, FX_Samples[num], NULL, TRUE) & 4095; if (chan < 0) return -1; // channel was already playing if (chstatesa[chan] && FX_CallBackFunc) FX_CallBackFunc(chcallvals[chan]); // set pitch FSOUND_SetVolume(chan, vol); if (FSOUND_Sample_GetMode(FX_Samples[num]) & FSOUND_STEREO) FSOUND_SetPan(chan, FSOUND_STEREOPAN); else FSOUND_SetPan(chan, 128); FSOUND_SetLoopMode(chan, FSOUND_LOOP_NORMAL); chcallvals[chan] = num; FSOUND_SetPaused(chan, FALSE); dprintOSD("FX_PlayLoopedSound(): Play sound %d in channel %d\n",num,chan); return chan;}int32_t FX_PlayPositionedSound( int32_t pitchoffset, int32_t angle, int32_t distance, uint32_t num){ int32_t chan; FX_SimulateCallbacks(); if (!FX_Samples[num]) return -1; chan = FSOUND_PlaySoundEx(FSOUND_FREE, FX_Samples[num], NULL, TRUE) & 4095; if (chan < 0) return -1; // channel was already playing if (chstatesa[chan] && FX_CallBackFunc) FX_CallBackFunc(chcallvals[chan]); if (angle<0) angle = 255-angle; // behind us // set pitch FSOUND_SetVolume(chan,255); FSOUND_SetPan(chan,128); FSOUND_SetLoopMode(chan, FSOUND_LOOP_OFF); chcallvals[chan] = num; FSOUND_SetPaused(chan, FALSE); dprintOSD("FX_PlayPositionedSound(): Play sound %d in channel %d\n",num,chan); return chan;}int32_t FX_LoadSample(char *ptr, int32_t size, uint32_t number, int32_t priority){ FSOUND_SAMPLE *samp = NULL; int32_t samplerate=0, channels=0, samplesize=0; int32_t flags=0; int32_t datalen=0; void *ptr1,*ptr2; int32_t ptr1len,ptr2len; if (!memcmp(ptr, "Creative Voice File", 0x13)) { // VOC file if (FX_ReadVOCInfo(ptr,size,&samplerate,&channels,&samplesize,&datalen) == 0) { flags |= (channels==2)?FSOUND_STEREO:FSOUND_MONO; flags |= (samplesize==16)?FSOUND_16BITS:FSOUND_8BITS; flags |= FSOUND_SIGNED; samp = FSOUND_Sample_Alloc(number, (datalen >> (channels-1)) / (samplesize>>3), flags, samplerate, -1, -1, priority); if (samp) { if (FSOUND_Sample_Lock(samp,0,datalen,&ptr1,&ptr2,&ptr1len,&ptr2len)) { if (FX_ReadVOCData(ptr,ptr1,datalen,(samplesize==8))) ; FSOUND_Sample_Unlock(samp,ptr1,ptr2,ptr1len,ptr2len); } } } } else { samp = FSOUND_Sample_Load(number, ptr, FSOUND_LOADMEMORY, size); } dprintOSD("FX_LoadSample(): loaded sound %d\n",number); if (samp) FSOUND_Sample_SetDefaults(samp, -1, -1, -1, priority); FX_Samples[number] = samp; return (samp != NULL);}int32_t FX_SampleLoaded(uint32_t number){ return (FX_Samples[number] != NULL);}#define REGRESSTC(tc) (256000000/(65536-(tc)))#define REGRESSSR(sr) (1000000/(256-(sr)))int32_t FX_ReadVOCInfo(char *data, int32_t size, int32_t *samplerate, int32_t *channels, int32_t *samplesize, int32_t *datalen){ int16_t version,version2; char blocktype=0; int32_t blocklen=0; char *ptr=data; if (memcmp(ptr, "Creative Voice File\x1A", 0x14)) return -1; ptr += 0x14; ptr += 2; version = ((int16_t*)ptr)[0]; version2 = ((int16_t*)ptr)[1]; if (~version + 0x1234 != version2) return -1; ptr += 4; while (1) { blocktype = *(ptr++); if ((ptr-data)>size) return -1; // truncated if (blocktype == 0) break; blocklen = *(ptr++); blocklen |= *(ptr++) << 8; blocklen |= *(ptr++) << 16; switch (blocktype) { case 1: /* sound data begin block */ if (!*samplerate) *samplerate = REGRESSSR(ptr[0]); if (ptr[1] != 0) { /* only 8-bit files please */ return -1; } if (!*channels) *channels = 1; *samplesize = 8; *datalen += blocklen-2; ptr += blocklen; break; case 2: /* sound continue */ *datalen += blocklen; ptr += blocklen; break;#if 0 case 3: /* silence */ kread(fh, blockprop, 3); /* length = blockprop[0] | (blockprop[1] << 8) sample rate = REGRESSSR(blockprop[2])) */ break; case 4: /* marker */ kread(fh, &blockprop, 2); /* id = blockprop[0] | (blockprop[1] << 8)) */ break; case 5: /* ASCII data */ klseek(fh, blocklen, SEEK_CUR); /* asciiz string */ break; case 6: /* repeat */ kread(fh, blockprop, 2); /* num repetitions = (blockprop[0] | (blockprop[1] << 8)) - 1 */ break; case 7: /* end repeat */ break;#endif case 8: /* sound attribute extension block */ *samplerate = REGRESSTC(ptr[0] | (ptr[1] << 8)); *samplesize = 8; if (ptr[3] == 1) { *samplerate >>= 1; *channels = 2; } else *channels = 1; if (ptr[2] != 0) { /* only 8-bit files please */ return -1; } ptr += 4; /* a block 1 follows */ break; case 9: /* sound data format 3 */ *samplerate = *((int32_t*)(ptr)); *samplesize = ptr[4]; *channels = ptr[5]; if ((ptr[6] | (ptr[7] << 8)) != 0 && (ptr[6] | (ptr[7] << 8)) != 4) { /* only PCM please */ return -1; } *datalen += blocklen-12; ptr += blocklen; break; default: ptr += blocklen; break; } } return 0;}int32_t FX_ReadVOCData(char *data, char *buf, int32_t bufferlen, char eightbit){ int16_t offset; char blocktype=0; int32_t blocklen=0, br; data += 0x14 + 2 + 4; while (bufferlen>0) { blocktype = *(data++); if (blocktype == 0) break; blocklen = *(data++); blocklen |= *(data++) << 8; blocklen |= *(data++) << 16; switch (blocktype) { case 1: /* sound data */ data += 2; br = min(blocklen-2, bufferlen); goto convertdata; case 2: /* sound continue */ br = min(blocklen, bufferlen); goto convertdata; case 9: /* sound data format 3 */ data += 12; br = min(blocklen-12, bufferlen); goto convertdata; default: data += blocklen; continue; }convertdata: bufferlen -= br; if (eightbit) { // FMOD wants signed data for (; br>0; br--) *(buf++) = (uint8_t)((int16_t)(*(data++)) - 0x80); } else { memcpy(buf,data,br); buf += br; data += br; } } return 0;}int32_t FX_SimulateCallbacks(void){ int32_t i; if (!FX_CallBackFunc || !chstates) return 0; chstatesa = chstates + (FX_NumVoices * chtoggle); chstatesb = chstates + (FX_NumVoices * (chtoggle^1)); for (i=0;i<FX_NumVoices;i++) { chstatesa[i] = FSOUND_IsPlaying(i); if (chstatesa[i] == chstatesb[i]) continue; // channel is still silent/playing if (chstatesa[i] > chstatesb[i]) continue; // channel has begun playing // channel has ended playing FX_CallBackFunc(chcallvals[i]); dprintOSD("FX_SimulateCallbacks(): channel %d ended sound %d\n",i,chcallvals[i]); } chtoggle ^= 1; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -