📄 mixdrv.c
字号:
/* * $Id: mixdrv.c 1.13 1996/09/08 21:14:54 chasan released $ * 1.14 1998/10/24 18:20:53 chasan released (Mixer API) * * Software-based waveform synthesizer emulator driver. * * Copyright (C) 1995-1999 Carlos Hasan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */#define __FILTER__#ifdef __GNUC__#include <memory.h>#define cdecl#endif#include <string.h>#include <malloc.h>#include "audio.h"#include "drivers.h"/* * Voice control bit fields */#define VOICE_STOP 0x01#define VOICE_16BITS 0x02#define VOICE_LOOP 0x04#define VOICE_BIDILOOP 0x08#define VOICE_REVERSE 0x10/* * Voice pitch accurary and mixing buffer size */#define ACCURACY 12#define BUFFERSIZE 512/* * Waveform synthesizer voice structure */typedef struct { LPVOID lpData; LONG dwAccum; LONG dwFrequency; LONG dwLoopStart; LONG dwLoopEnd; BYTE nVolume; BYTE nPanning; BYTE bControl; BYTE bReserved;} VOICE, *LPVOICE;/* * Low level voice mixing routine prototype */typedef VOID (cdecl* LPFNMIXAUDIO)(LPLONG, UINT, LPVOICE);/* * Waveform synthesizer state structure */static struct { VOICE aVoices[AUDIO_MAX_VOICES]; UINT nVoices; UINT wFormat; UINT nSampleRate; LONG dwTimerRate; LONG dwTimerAccum; LPBYTE lpMemory; LPFNAUDIOTIMER lpfnAudioTimer; LPFNMIXAUDIO lpfnMixAudioProc[2];} Synth;LPLONG lpVolumeTable;LPBYTE lpFilterTable;static VOID AIAPI UpdateVoices(LPBYTE lpData, UINT nCount);/* low level resamplation and quantization routines */#ifdef __ASM__VOID cdecl QuantAudioData08(LPVOID lpBuffer, LPLONG lpData, UINT nCount);VOID cdecl QuantAudioData16(LPVOID lpBuffer, LPLONG lpData, UINT nCount);VOID cdecl MixAudioData08M(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);VOID cdecl MixAudioData08S(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);VOID cdecl MixAudioData08MI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);VOID cdecl MixAudioData08SI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);VOID cdecl MixAudioData16M(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);VOID cdecl MixAudioData16S(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);VOID cdecl MixAudioData16MI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);VOID cdecl MixAudioData16SI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);static VOID QuantAudioData(LPVOID lpBuffer, LPLONG lpData, UINT nCount){ if (Synth.wFormat & AUDIO_FORMAT_16BITS) QuantAudioData16(lpBuffer, lpData, nCount); else QuantAudioData08(lpBuffer, lpData, nCount);}#elsetypedef short SHORT;typedef SHORT* LPSHORT;static VOID QuantAudioData(LPVOID lpBuffer, LPLONG lpData, UINT nCount){ LPSHORT lpwBuffer; LPBYTE lpbBuffer; LONG dwSample; if (Synth.wFormat & AUDIO_FORMAT_16BITS) { lpwBuffer = (LPSHORT) lpBuffer; while (nCount-- > 0) { dwSample = *lpData++; if (dwSample < -32768) dwSample = -32768; else if (dwSample > +32767) dwSample = +32767; *lpwBuffer++ = (SHORT) dwSample; } } else { lpbBuffer = (LPBYTE) lpBuffer; while (nCount-- > 0) { dwSample = *lpData++; if (dwSample < -32768) dwSample = -32768; else if (dwSample > +32767) dwSample = +32767; *lpbBuffer++ = (BYTE) ((dwSample >> 8) + 128); } }}static VOID AIAPIMixAudioData08M(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice){ register UINT count; register DWORD accum, delta; register LPLONG table, buf; register LPBYTE data; accum = lpVoice->dwAccum; delta = lpVoice->dwFrequency; table = lpVolumeTable + ((UINT) lpVoice->nVolume << 8); data = lpVoice->lpData; buf = lpBuffer; count = nCount; do { *buf++ += table[data[accum >> ACCURACY]]; accum += delta; } while (--count != 0); lpVoice->dwAccum = accum;}#define min(a, b) ((a) < (b) ? (a) : (b))static VOID AIAPIMixAudioData08S(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice){ register UINT a; register DWORD accum, delta; register LPLONG ltable, rtable, buf; register LPBYTE data; accum = lpVoice->dwAccum; delta = lpVoice->dwFrequency; a = ((UINT) lpVoice->nVolume * lpVoice->nPanning) >> 8; rtable = lpVolumeTable + (a << 8); ltable = lpVolumeTable + ((lpVoice->nVolume - a) << 8); data = lpVoice->lpData; buf = lpBuffer; do { a = data[accum >> ACCURACY]; buf[0] += ltable[a]; buf[1] += rtable[a]; accum += delta; buf += 2; } while (--nCount != 0); lpVoice->dwAccum = accum;}static VOID AIAPIMixAudioData08MI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice){ register INT a, frac; register DWORD accum, delta; register LPLONG table, buf; register LPBYTE data, ftable; /* adaptive oversampling interpolation comparison */ if (lpVoice->dwFrequency < -(1 << ACCURACY) || lpVoice->dwFrequency > +(1 << ACCURACY)) { MixAudioData08M(lpBuffer, nCount, lpVoice); return; } accum = lpVoice->dwAccum; delta = lpVoice->dwFrequency; table = lpVolumeTable + ((UINT) lpVoice->nVolume << 8); data = lpVoice->lpData; buf = lpBuffer;#ifdef __FILTER__ a = (BYTE) lpVoice->bReserved; frac = ((long) delta < 0 ? -delta : +delta) >> (ACCURACY - 5); ftable = lpFilterTable + (frac << 8); do { a = (BYTE)(a + ftable[data[accum >> ACCURACY]] - ftable[a]); *buf++ += table[a]; accum += delta; } while (--nCount != 0); lpVoice->bReserved = (BYTE) a;#else do { register INT b; a = (signed char) data[accum >> ACCURACY]; b = (signed char) data[(accum >> ACCURACY) + 1]; frac = (accum & ((1 << ACCURACY) - 1)) >> (ACCURACY - 5); a = (BYTE)(a + ((frac * (b - a)) >> 5)); *buf++ += table[a]; accum += delta; } while (--nCount != 0);#endif lpVoice->dwAccum = accum;}static VOID AIAPIMixAudioData08SI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice){ register INT a, frac; register DWORD accum, delta; register LPLONG buf, ltable, rtable; register LPBYTE data, ftable; /* adaptive oversampling interpolation comparison */ if (lpVoice->dwFrequency < -(1 << ACCURACY) || lpVoice->dwFrequency > +(1 << ACCURACY)) { MixAudioData08S(lpBuffer, nCount, lpVoice); return; } accum = lpVoice->dwAccum; delta = lpVoice->dwFrequency; a = ((UINT) lpVoice->nVolume * lpVoice->nPanning) >> 8; rtable = lpVolumeTable + (a << 8); ltable = lpVolumeTable + ((lpVoice->nVolume - a) << 8); data = lpVoice->lpData; buf = lpBuffer;#ifdef __FILTER__ a = (BYTE) lpVoice->bReserved; frac = ((long) delta < 0 ? -delta : +delta) >> (ACCURACY - 5); ftable = lpFilterTable + (frac << 8); do { a = (BYTE)(a + ftable[data[accum >> ACCURACY]] - ftable[a]); buf[0] += ltable[a]; buf[1] += rtable[a]; accum += delta; buf += 2; } while (--nCount != 0); lpVoice->bReserved = (BYTE) a;#else do { register INT b; a = (signed char) data[accum >> ACCURACY]; b = (signed char) data[(accum >> ACCURACY) + 1]; frac = (accum & ((1 << ACCURACY) - 1)) >> (ACCURACY - 5); a = (BYTE)(a + ((frac * (b - a)) >> 5)); buf[0] += ltable[a]; buf[1] += rtable[a]; accum += delta; buf += 2; } while (--nCount != 0);#endif lpVoice->dwAccum = accum;}static VOID AIAPIMixAudioData16M(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice){ register UINT a, count; register DWORD accum, delta; register LPLONG table, buf; register LPWORD data; accum = lpVoice->dwAccum; delta = lpVoice->dwFrequency; table = lpVolumeTable + ((UINT) lpVoice->nVolume << 8); data = lpVoice->lpData; buf = lpBuffer; count = nCount; do { a = data[accum >> ACCURACY]; *buf++ += table[a >> 8]; accum += delta; } while (--count != 0); lpVoice->dwAccum = accum;}static VOID AIAPIMixAudioData16S(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice){ register UINT a; register DWORD accum, delta; register LPLONG ltable, rtable, buf; register LPWORD data; accum = lpVoice->dwAccum; delta = lpVoice->dwFrequency; a = ((UINT) lpVoice->nVolume * lpVoice->nPanning) >> 8; rtable = lpVolumeTable + (a << 8); ltable = lpVolumeTable + ((lpVoice->nVolume - a) << 8); data = lpVoice->lpData; buf = lpBuffer; do { a = data[accum >> ACCURACY]; buf[0] += ltable[a >> 8]; buf[1] += rtable[a >> 8]; accum += delta; buf += 2; } while (--nCount != 0); lpVoice->dwAccum = accum;}static VOID AIAPIMixAudioData16MI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice){ register UINT frac, count; register DWORD a, b, accum, delta; register LPLONG table, buf; register LPWORD data; /* adaptive oversampling interpolation comparison */ if (lpVoice->dwFrequency < -(1 << ACCURACY) || lpVoice->dwFrequency > +(1 << ACCURACY)) { MixAudioData16M(lpBuffer, nCount, lpVoice); return; } accum = lpVoice->dwAccum; delta = lpVoice->dwFrequency; table = lpVolumeTable + ((UINT) lpVoice->nVolume << 8); data = lpVoice->lpData; buf = lpBuffer; count = nCount; do { a = data[accum >> ACCURACY]; b = data[(accum >> ACCURACY) + 1]; frac = (accum & ((1 << ACCURACY) - 1)) >> (ACCURACY - 5); a = (WORD)((SHORT)a + ((frac * ((SHORT)b - (SHORT)a)) >> 5)); *buf++ += table[a >> 8]; accum += delta; } while (--count != 0); lpVoice->dwAccum = accum;}static VOID AIAPIMixAudioData16SI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice){ register UINT frac; register DWORD a, b, accum, delta; register LPLONG ltable, rtable, buf; register LPWORD data; /* adaptive oversampling interpolation comparison */ if (lpVoice->dwFrequency < -(1 << ACCURACY) || lpVoice->dwFrequency > +(1 << ACCURACY)) { MixAudioData16S(lpBuffer, nCount, lpVoice); return; } accum = lpVoice->dwAccum; delta = lpVoice->dwFrequency; a = ((UINT) lpVoice->nVolume * lpVoice->nPanning) >> 8; rtable = lpVolumeTable + (a << 8); ltable = lpVolumeTable + ((lpVoice->nVolume - a) << 8); data = lpVoice->lpData; buf = lpBuffer; do { a = data[accum >> ACCURACY]; b = data[(accum >> ACCURACY) + 1]; frac = (accum & ((1 << ACCURACY) - 1)) >> (ACCURACY - 5); a = (WORD)((SHORT)a + ((frac * ((int)(SHORT)b - (int)(SHORT)a)) >> 5)); buf[0] += ltable[a >> 8]; buf[1] += rtable[a >> 8]; accum += delta; buf += 2; } while (--nCount != 0); lpVoice->dwAccum = accum;}#endifstatic VOID MixAudioData(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice){ UINT nSize; if (Synth.wFormat & AUDIO_FORMAT_STEREO) nCount >>= 1; while (nCount > 0 && !(lpVoice->bControl & VOICE_STOP)) { /* check boundary conditions */ if (lpVoice->bControl & VOICE_REVERSE) { if (lpVoice->dwAccum < lpVoice->dwLoopStart) { if (lpVoice->bControl & VOICE_BIDILOOP) { lpVoice->dwAccum = lpVoice->dwLoopStart + (lpVoice->dwLoopStart - lpVoice->dwAccum); lpVoice->bControl ^= VOICE_REVERSE; continue; } else if (lpVoice->bControl & VOICE_LOOP) { lpVoice->dwAccum = lpVoice->dwLoopEnd - (lpVoice->dwLoopStart - lpVoice->dwAccum); continue; } else { lpVoice->bControl |= VOICE_STOP; break; } } } else { if (lpVoice->dwAccum > lpVoice->dwLoopEnd) { if (lpVoice->bControl & VOICE_BIDILOOP) { lpVoice->dwAccum = lpVoice->dwLoopEnd - (lpVoice->dwAccum - lpVoice->dwLoopEnd); lpVoice->bControl ^= VOICE_REVERSE; continue; } else if (lpVoice->bControl & VOICE_LOOP) { lpVoice->dwAccum = lpVoice->dwLoopStart + (lpVoice->dwAccum - lpVoice->dwLoopEnd); continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -