📄 mixdrv.c
字号:
} else { lpVoice->bControl |= VOICE_STOP; break; } } } /* check for overflow and clip if necessary */ nSize = nCount; if (lpVoice->bControl & VOICE_REVERSE) { if (nSize * lpVoice->dwFrequency > lpVoice->dwAccum - lpVoice->dwLoopStart) nSize = (lpVoice->dwAccum - lpVoice->dwLoopStart + lpVoice->dwFrequency) / lpVoice->dwFrequency; } else { if (nSize * lpVoice->dwFrequency > lpVoice->dwLoopEnd - lpVoice->dwAccum) nSize = (lpVoice->dwLoopEnd - lpVoice->dwAccum + lpVoice->dwFrequency) / lpVoice->dwFrequency; } if (lpVoice->bControl & VOICE_REVERSE) lpVoice->dwFrequency = -lpVoice->dwFrequency; /* mixes chunk of data in a burst mode */ if (lpVoice->bControl & VOICE_16BITS) { Synth.lpfnMixAudioProc[1] (lpBuffer, nSize, lpVoice); } else { Synth.lpfnMixAudioProc[0] (lpBuffer, nSize, lpVoice); } if (lpVoice->bControl & VOICE_REVERSE) lpVoice->dwFrequency = -lpVoice->dwFrequency; /* update mixing buffer address and counter */ lpBuffer += nSize; if (Synth.wFormat & AUDIO_FORMAT_STEREO) lpBuffer += nSize; nCount -= nSize; }}static VOID MixAudioVoices(LPLONG lpBuffer, UINT nCount){ UINT nVoice, nSize; while (nCount > 0) { nSize = nCount; if (Synth.lpfnAudioTimer != NULL) { nSize = (Synth.dwTimerRate - Synth.dwTimerAccum + 64L) & ~63L; if (nSize > nCount) nSize = nCount; if ((Synth.dwTimerAccum += nSize) >= Synth.dwTimerRate) { Synth.dwTimerAccum -= Synth.dwTimerRate; Synth.lpfnAudioTimer(); } } for (nVoice = 0; nVoice < Synth.nVoices; nVoice++) { MixAudioData(lpBuffer, nSize, &Synth.aVoices[nVoice]); } lpBuffer += nSize; nCount -= nSize; }}/* * High level waveform synthesizer interface */static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps){ memset(lpCaps, 0, sizeof(AUDIOCAPS)); return AUDIO_ERROR_NOTSUPPORTED;}static UINT AIAPI PingAudio(VOID){ return AUDIO_ERROR_NOTSUPPORTED;}static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo){ memset(&Synth, 0, sizeof(Synth)); Synth.wFormat = lpInfo->wFormat; Synth.nSampleRate = lpInfo->nSampleRate; if (Synth.wFormat & AUDIO_FORMAT_FILTER) { Synth.lpfnMixAudioProc[0] = (Synth.wFormat & AUDIO_FORMAT_STEREO) ? MixAudioData08SI : MixAudioData08MI; Synth.lpfnMixAudioProc[1] = (Synth.wFormat & AUDIO_FORMAT_STEREO) ? MixAudioData16SI : MixAudioData16MI; } else { Synth.lpfnMixAudioProc[0] = (Synth.wFormat & AUDIO_FORMAT_STEREO) ? MixAudioData08S : MixAudioData08M; Synth.lpfnMixAudioProc[1] = (Synth.wFormat & AUDIO_FORMAT_STEREO) ? MixAudioData16S : MixAudioData16M; } /* allocate volume (0-64) and filter (0-31) table */ Synth.lpMemory = malloc(sizeof(LONG) * 65 * 256 + sizeof(BYTE) * 32 * 256 + 1023); if (Synth.lpMemory != NULL) { lpVolumeTable = (LPLONG) (((DWORD) Synth.lpMemory + 1023) & ~1023); lpFilterTable = (LPBYTE) (lpVolumeTable + 65 * 256); ASetAudioMixerValue(AUDIO_MIXER_MASTER_VOLUME, 96); ASetAudioCallback(UpdateVoices); return AUDIO_ERROR_NONE; } return AUDIO_ERROR_NOMEMORY;}static UINT AIAPI CloseAudio(VOID){ if (Synth.lpMemory != NULL) free(Synth.lpMemory); memset(&Synth, 0, sizeof(Synth)); return AUDIO_ERROR_NONE;}static UINT AIAPI SetAudioMixerValue(UINT nChannel, UINT nMixerValue){ LPBYTE lpFilter; LPLONG lpVolume; UINT nVolume, nSample; LONG dwAccum, dwDelta; if (Synth.lpMemory == NULL) return AUDIO_ERROR_NOTSUPPORTED; /* master volume must be less than 256 units */ if (nChannel != AUDIO_MIXER_MASTER_VOLUME || nMixerValue > 256) return AUDIO_ERROR_INVALPARAM; /* half dynamic range for mono output */ if (!(Synth.wFormat & AUDIO_FORMAT_STEREO)) nMixerValue >>= 1; /* build volume table (0-64) */ lpVolume = lpVolumeTable; dwDelta = 0; for (nVolume = 0; nVolume <= 64; nVolume++, dwDelta += nMixerValue) { dwAccum = 0; for (nSample = 0; nSample < 128; nSample++, dwAccum += dwDelta) *lpVolume++ = dwAccum >> 4; dwAccum = -dwAccum; for (nSample = 0; nSample < 128; nSample++, dwAccum += dwDelta) *lpVolume++ = dwAccum >> 4; }#ifdef __FILTER__ /* build lowpass filter table (0-31) */ lpFilter = lpFilterTable; for (nVolume = 0; nVolume < 32; nVolume++) { dwAccum = 0; for (nSample = 0; nSample < 128; nSample++, dwAccum += nVolume) *lpFilter++ = dwAccum >> 5; dwAccum = -dwAccum; for (nSample = 0; nSample < 128; nSample++, dwAccum += nVolume) *lpFilter++ = dwAccum >> 5; }#endif return AUDIO_ERROR_NONE;}static UINT AIAPI OpenVoices(UINT nVoices){ UINT nVoice; /* * Initialize waveform synthesizer structure for playback */ if (nVoices >= 1 && nVoices <= AUDIO_MAX_VOICES) { Synth.nVoices = nVoices; for (nVoice = 0; nVoice < Synth.nVoices; nVoice++) Synth.aVoices[nVoice].bControl = VOICE_STOP; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM;}static UINT AIAPI CloseVoices(VOID){ UINT nVoice; memset(Synth.aVoices, 0, sizeof(Synth.aVoices)); for (nVoice = 0; nVoice < AUDIO_MAX_VOICES; nVoice++) Synth.aVoices[nVoice].bControl = VOICE_STOP; return AUDIO_ERROR_NONE;}static UINT AIAPI UpdateAudio(VOID){ return AUDIO_ERROR_NONE;}static LONG AIAPI GetAudioDataAvail(VOID){ return 0;}static UINT AIAPI CreateAudioData(LPAUDIOWAVE lpWave){ if (lpWave != NULL) { lpWave->dwHandle = (DWORD) lpWave->lpData; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI DestroyAudioData(LPAUDIOWAVE lpWave){ if (lpWave != NULL && lpWave->dwHandle != 0) { return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI WriteAudioData(LPAUDIOWAVE lpWave, DWORD dwOffset, UINT nCount){ if (lpWave != NULL && lpWave->dwHandle != 0) { /* anticlick removal work around */ if (lpWave->wFormat & AUDIO_FORMAT_LOOP) { *(LPSTR)(lpWave->dwHandle + lpWave->dwLoopEnd) = *(LPSTR)(lpWave->dwHandle + lpWave->dwLoopStart); } else if (dwOffset + nCount >= lpWave->dwLength) { *(LPDWORD) (lpWave->dwHandle + lpWave->dwLength) = 0; } return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI PrimeVoice(UINT nVoice, LPAUDIOWAVE lpWave){ LPVOICE lpVoice; if (nVoice < Synth.nVoices && lpWave != NULL && lpWave->dwHandle != 0) { lpVoice = &Synth.aVoices[nVoice]; lpVoice->lpData = (LPVOID) lpWave->dwHandle; lpVoice->bControl = VOICE_STOP; lpVoice->dwAccum = 0; if (lpWave->wFormat & (AUDIO_FORMAT_LOOP | AUDIO_FORMAT_BIDILOOP)) { lpVoice->dwLoopStart = lpWave->dwLoopStart; lpVoice->dwLoopEnd = lpWave->dwLoopEnd; lpVoice->bControl |= VOICE_LOOP; if (lpWave->wFormat & AUDIO_FORMAT_BIDILOOP) lpVoice->bControl |= VOICE_BIDILOOP; } else { lpVoice->dwLoopStart = lpWave->dwLength; lpVoice->dwLoopEnd = lpWave->dwLength; } if (lpWave->wFormat & AUDIO_FORMAT_16BITS) { lpVoice->dwLoopStart >>= 1; lpVoice->dwLoopEnd >>= 1; lpVoice->bControl |= VOICE_16BITS; } lpVoice->dwAccum <<= ACCURACY; lpVoice->dwLoopStart <<= ACCURACY; lpVoice->dwLoopEnd <<= ACCURACY; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI StartVoice(UINT nVoice){ if (nVoice < Synth.nVoices) { Synth.aVoices[nVoice].bControl &= ~VOICE_STOP; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI StopVoice(UINT nVoice){ if (nVoice < Synth.nVoices) { Synth.aVoices[nVoice].bControl |= VOICE_STOP; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI SetVoicePosition(UINT nVoice, LONG dwPosition){ if (nVoice < Synth.nVoices) { dwPosition <<= ACCURACY; if (dwPosition >= 0 && dwPosition < Synth.aVoices[nVoice].dwLoopEnd) { Synth.aVoices[nVoice].dwAccum = dwPosition; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI SetVoiceFrequency(UINT nVoice, LONG dwFrequency){ if (nVoice < Synth.nVoices) { if (dwFrequency >= AUDIO_MIN_FREQUENCY && dwFrequency <= AUDIO_MAX_FREQUENCY) { Synth.aVoices[nVoice].dwFrequency = ((dwFrequency << ACCURACY) + (Synth.nSampleRate >> 1)) / Synth.nSampleRate; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI SetVoiceVolume(UINT nVoice, UINT nVolume){ if (nVoice < Synth.nVoices) { if (nVolume <= AUDIO_MAX_VOLUME) { Synth.aVoices[nVoice].nVolume = nVolume >> 1; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI SetVoicePanning(UINT nVoice, UINT nPanning){ if (nVoice < Synth.nVoices) { if (nPanning <= AUDIO_MAX_PANNING) { Synth.aVoices[nVoice].nPanning = nPanning; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI GetVoicePosition(UINT nVoice, LPLONG lpdwPosition){ if (nVoice < Synth.nVoices) { if (lpdwPosition != NULL) { *lpdwPosition = Synth.aVoices[nVoice].dwAccum >> ACCURACY; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI GetVoiceFrequency(UINT nVoice, LPLONG lpdwFrequency){ if (nVoice < Synth.nVoices) { if (lpdwFrequency != NULL) { *lpdwFrequency = (Synth.aVoices[nVoice].dwFrequency * Synth.nSampleRate) >> ACCURACY; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI GetVoiceVolume(UINT nVoice, LPUINT lpnVolume){ if (nVoice < Synth.nVoices) { if (lpnVolume != NULL) { *lpnVolume = Synth.aVoices[nVoice].nVolume << 1; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI GetVoicePanning(UINT nVoice, LPUINT lpnPanning){ if (nVoice < Synth.nVoices) { if (lpnPanning != NULL) { *lpnPanning = Synth.aVoices[nVoice].nPanning; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI GetVoiceStatus(UINT nVoice, LPBOOL lpnStatus){ if (nVoice < Synth.nVoices) { if (lpnStatus != NULL) { *lpnStatus = (Synth.aVoices[nVoice].bControl & VOICE_STOP) != 0; return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM; } return AUDIO_ERROR_INVALHANDLE;}static UINT AIAPI SetAudioTimerProc(LPFNAUDIOTIMER lpfnAudioTimer){ Synth.lpfnAudioTimer = lpfnAudioTimer; return AUDIO_ERROR_NONE;}static UINT AIAPI SetAudioTimerRate(UINT nBPM){ if (nBPM >= 0x20 && nBPM <= 0xFF) { Synth.dwTimerRate = Synth.nSampleRate; if (Synth.wFormat & AUDIO_FORMAT_STEREO) Synth.dwTimerRate <<= 1; Synth.dwTimerRate = (5 * Synth.dwTimerRate) / (2 * nBPM); return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM;}static VOID AIAPI UpdateVoices(LPBYTE lpData, UINT nCount){ static LONG aBuffer[BUFFERSIZE]; UINT nSamples; if (Synth.wFormat & AUDIO_FORMAT_16BITS) nCount >>= 1; while (nCount > 0) { if ((nSamples = nCount) > BUFFERSIZE) nSamples = BUFFERSIZE; memset(aBuffer, 0, nSamples << 2); MixAudioVoices(aBuffer, nSamples); QuantAudioData(lpData, aBuffer, nSamples); lpData += nSamples << ((Synth.wFormat & AUDIO_FORMAT_16BITS) != 0); nCount -= nSamples; }}/* * Waveform synthesizer public interface */AUDIOSYNTHDRIVER EmuSynthDriver ={ GetAudioCaps, PingAudio, OpenAudio, CloseAudio, UpdateAudio, OpenVoices, CloseVoices, SetAudioTimerProc, SetAudioTimerRate, SetAudioMixerValue, GetAudioDataAvail, CreateAudioData, DestroyAudioData, WriteAudioData, PrimeVoice, StartVoice, StopVoice, SetVoicePosition, SetVoiceFrequency, SetVoiceVolume, SetVoicePanning, GetVoicePosition, GetVoiceFrequency, GetVoiceVolume, GetVoicePanning, GetVoiceStatus};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -