Hello,
I am trying to make a dll that can produce any kind of sine waves mixed
together. It works partly, but when I set the panning to -.1 for example,
the playing stops. some strange things happen that I do not understand. I
use Dev-CPP to compile.
Any kind of feedback is appreciated.
Marc.
/////////////// frmMain (Visual Basic 6.0) //////////
Option Explicit
Private Const ERR_NOERROR = 0
Private Const ERR_PLAYING = -1
Private Const ERR_MAXCH = -2
Private Const ERR_OUTOFRANGE = -3
Private Const ERR_NOCHANNELS = -4
Private Const ERR_OUTOFMEMORY = -5
Private Const ERR_DEVICENOTREADY = -6
Private Const ERR_CANNOTSAVE = -7
Private Const ERR_NOTPLAYING = -8
Private Const ERR_NOTRECORDING = -9
Private Declare Function SetPhase Lib "SecretSound.dll" (ByVal Channel As
Long, ByVal Phase As Double) As Integer
Private Declare Function SetPan Lib "SecretSound.dll" (ByVal Channel As
Long, ByVal Pan As Double) As Integer
Private Declare Function SetMasterVolume Lib "SecretSound.dll" (ByVal
Volume
As Double) As Integer
Private Declare Function SetVolume Lib "SecretSound.dll" (ByVal Channel As
Long, ByVal Volume As Double) As Integer
Private Declare Function SetFrequency Lib "SecretSound.dll" (ByVal Channel
As Long, ByVal Frequency As Double) As Integer
Private Declare Function StartSound Lib "SecretSound.dll" () As Integer
Private Declare Function StopSound Lib "SecretSound.dll" () As Integer
Private Declare Function SetChannel Lib "SecretSound.dll" (ByVal Channel
As
Integer, ByVal Volume As Double, ByVal Pan As Double, ByVal Frequency As
Double, ByVal Phase As Double) As Integer
Private Declare Function SetChannels Lib "SecretSound.dll" (ByRef Volume
As
Double, ByRef Pan As Double, ByRef Frequency As Double, ByRef Phase As
Double) As Integer
Private Declare Function SetNumberOfChannels Lib "SecretSound.dll" (ByVal
N
As Long) As Integer
Private Declare Function SetAutoRange Lib "SecretSound.dll" (ByVal b As
Long) As Integer
Private Declare Function SaveSound Lib "SecretSound.dll" (ByVal sFileName
As
String, ByVal dLength As Double) As Integer
Private Declare Function StartRecording Lib "SecretSound.dll" (ByVal
sFileName As String) As Integer
Private Declare Function StopRecording Lib "SecretSound.dll" () As Integer
Private Declare Function MyFFT Lib "SecretSound.dll" (ByVal lNin As Long,
ByRef dInArray As Double, ByVal lNout As Long, ByRef dOutArray As Double,
ByVal dFromHz As Double, ByVal dToHz As Double, ByVal dResolution As
Double,
ByVal dSampleRate As Double) As Integer
Const NCH = 10
Const PI = 3.141592653589
Dim freq(NCH - 1) As Double
Dim vol(NCH - 1) As Double
Dim Phase(NCH - 1) As Double
Dim Pan(NCH - 1) As Double
.....
Private Sub cmdSet_Click()
lblStatus = "Ready"
GetSettings
Dim i As Integer
ret = SetMasterVolume(Master)
If ret <> 0 Then ShowRet ("SetMaster"): Exit Sub
For i = 0 To NCH - 1
ret = SetChannel(i, vol(i), Pan(i), freq(i), Phase(i))
If ret <> 0 Then ShowRet ("SetCh"): Exit Sub
Next i
End Sub
//////////////// secretsound.h //////////////
#ifndef _DLL_H_
#define _DLL_H_
#if BUILDING_DLL
# define DLLIM****T __declspec (dllex****t)
#else /* Not BUILDING_DLL */
# define DLLIM****T __declspec (dllim****t)
#endif /* Not BUILDING_DLL */
#define SAMPLE_RATE 44100
#define OUT_BUFFER_SIZE 11024 // must be div 4 ! for recording:
blockalign
#define PI 3.1415926535897932384626433f
#define PIx2 6.2831853070f
#define MAX_CH 200
#define ERR_NOERROR 0
#define ERR_PLAYING -1
#define ERR_MAXCH -2
#define ERR_OUTOFRANGE -3
#define ERR_NOCHANNELS -4
#define ERR_OUTOFMEMORY -5
#define ERR_DEVICENOTREADY -6
#define ERR_CANNOTSAVE -7
#define ERR_NOTPLAYING -8
#define ERR_NOTRECORDING -9
// Global variables for sound settings
double dMyMasterVol;
short sMyNCh;
double dMyFreq[MAX_CH];
double dMyVol[MAX_CH];
double dMyPan[MAX_CH];
double dMyPhase[MAX_CH];
double dMyLRVol[1][MAX_CH];
int ret; // for return values
long lBytesRecorded ;
char pcMyFileName[FILENAME_MAX]="";
char pcMyTmpFileName[FILENAME_MAX]=""; // filename for recording
FILE *fMyTmp ;
BOOL bClosing, bAutoRange, bRecording ;
HWAVEOUT hWaveOut=NULL ;
PBYTE pBuffer1, pBuffer2 ;
PWAVEHDR pWaveHdr1, pWaveHdr2 ;
WAVEFORMATEX waveformat ;
FILE *fopen(), *fp;
// Functions to be ex****ted:
DLLIM****T short __stdcall StartRecording (char * pcFileName) ;
DLLIM****T short __stdcall StopRecording () ;
DLLIM****T short __stdcall SaveSound (char * pcFileName, double
dLength);
DLLIM****T short __stdcall SetAutoRange (short sAutoRange);
DLLIM****T short __stdcall SetNumberOfChannels (short sChannels);
DLLIM****T short __stdcall SetPhase (short sChannel, double dPhase);
DLLIM****T short __stdcall SetMasterVolume (double Volume);
DLLIM****T short __stdcall SetVolume (short sChannel, double dVolume);
DLLIM****T short __stdcall SetPan (short sChannel, double dPan);
DLLIM****T short __stdcall SetFrequency (short sChannel,double
dFrequency);
DLLIM****T short __stdcall SetChannel (short sChannel, double dVolume,
double dPan, double dFreq, double dPhase);
DLLIM****T short __stdcall SetChannels (double dVolume[], double
dPan[],
double dFreq[], double dPhase[]);
DLLIM****T short __stdcall StartSound () ;
DLLIM****T short __stdcall StopSound ();
DLLIM****T short __stdcall MyFFT (long lNin, double dInArray[], long
lNout, double dOutArray[], double dFromHz, double dToHz, double
dResolution,
double dSampleRate) ;
//---------------------------
void CALLBACK MyWaveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
DWORD_PTR dwParam1, DWORD_PTR dwParam2) ;
int WriteWaveData (long , PBYTE );
#endif /* _DLL_H_ */
/////////////////// .c /////////////////////
#define __UNICODE
#include <windows.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <tchar.h>
#include "secretsound.h"
int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ...)
{
TCHAR szBuffer [1024] ;
va_list pArgList ;
// The va_start macro (defined in STDARG.H) is usually
equivalent
to:
// pArgList = (char *) &szFormat + sizeof (szFormat) ;
va_start (pArgList, szFormat) ;
// The last argument to wvsprintf points to the arguments
_vsntprintf (szBuffer, sizeof (szBuffer) / sizeof (TCHAR),
szFormat, pArgList) ;
// The va_end macro just zeroes out pArgList for no good reason
va_end (pArgList) ;
return MessageBox (NULL, szBuffer, szCaption, 0) ;
}
VOID FillBuffer (PBYTE pBuffer, long lBufferLength)
{
static double dAngle[MAX_CH] ; // Locally stored phaseangles
long i, j ;
double dTmp, dTmpL, dTmpR ;
short iValueL, iValueR ;
// Generate the sound data
// Loop through the samples to be created
// Buffersize/4 because stereo 16 bit, buffer is in bytes
for (i = 0 ; i < lBufferLength / 4 ; i++)
{
dTmpL =0; // Each channel L/R
dTmpR =0;
// Loop through the channels, create a sine for each and increase
the wave angle accordingly
for (j = 0 ; j < sMyNCh ; j++)
{
dTmp = sin (dAngle[j] + dMyPhase[j]) ;
dTmpL += dMyLRVol[0][j] * dTmp;
dTmpR += dMyLRVol[1][j] * dTmp;
dAngle[j] += dMyFreq[j] ;
if (dAngle[j] > PIx2) dAngle[j] -= PIx2 ;
}
// Average the sMyNCh sines and apply master volume
if (bAutoRange)
{
dTmpL = dMyMasterVol * dTmpL / (double) sMyNCh ;
dTmpR = dMyMasterVol * dTmpR / (double) sMyNCh ;
} else {
dTmpL = dMyMasterVol * dTmpL ; // / (double) sMyNCh ;
dTmpR = dMyMasterVol * dTmpR ; // / (double) sMyNCh ;
}
iValueL = (short) (32767 * dTmpL) ;
iValueR = (short) (32767 * dTmpR) ;
pBuffer [i * 4] = (BYTE) (iValueL & 0x00ff) ;
pBuffer [i * 4 + 1] = (BYTE) ((iValueL >> 8) & 0xff);
pBuffer [i * 4 + 2] = (BYTE) (iValueR & 0x00ff) ;
pBuffer [i * 4 + 3] = (BYTE) ((iValueR >> 8) & 0xff);
}
// save the last buffer to file
if (bRecording) WriteWaveData (OUT_BUFFER_SIZE, pBuffer);
}
// code for saving wav
void put_str(FILE *fp, const char *str)
{
for (; *str; str++)
fputc(*str, fp);
}
void put_be16(FILE *fp, int val)
{
fputc((unsigned char) ((val >> 8) & 0xFF), fp);
fputc((unsigned char) ((val ) & 0xFF), fp);
}
void put_be32(FILE *fp, int val)
{
fputc((unsigned char) ((val >> 24) & 0xFF), fp);
fputc((unsigned char) ((val >> 16) & 0xFF), fp);
fputc((unsigned char) ((val >> 8) & 0xFF), fp);
fputc((unsigned char) ((val ) & 0xFF), fp);
}
void put_le16(FILE *fp, int val)
{
fputc((unsigned char) ((val ) & 0xFF), fp);
fputc((unsigned char) ((val >> 8) & 0xFF), fp);
}
void put_le32(FILE *fp, int val)
{
fputc((unsigned char) ((val ) & 0xFF), fp);
fputc((unsigned char) ((val >> 8) & 0xFF), fp);
fputc((unsigned char) ((val >> 16) & 0xFF), fp);
fputc((unsigned char) ((val >> 24) & 0xFF), fp);
}
int write_wav(char * pcFileName, long lLength,PBYTE pBuffer)
{
int i;
FILE *fp = fopen(pcFileName, "wb");
if (! fp) return ERR_CANNOTSAVE;
put_str(fp, "RIFF");
put_le32(fp, lLength + 12+18+8);
put_str(fp, "WAVE");
put_str(fp, "fmt ");
put_le32(fp, 18);
put_le16(fp, 1); // Format: 1 = PCM
put_le16(fp, 2); // Channels
put_le32(fp, SAMPLE_RATE); // SampleRate
put_le32(fp, SAMPLE_RATE * 4); // BytesPerSec
put_le16(fp, 4); // Alignment (channels * bytesPerSample)
put_le16(fp, 16); // BitsPerSample
put_le16(fp, 0);
put_str(fp, "data");
put_le32(fp, lLength);
for (i=0; i<lLength; i++)
{
fputc(pBuffer[i], fp);
}
fclose(fp);
return ERR_NOERROR;
}
int WriteWaveHeader (FILE *fp, long lLength)
{
put_str(fp, "RIFF");
put_le32(fp, lLength + 12+18+8);
put_str(fp, "WAVE");
put_str(fp, "fmt ");
put_le32(fp, 18);
put_le16(fp, 1); // Format: 1 = PCM
put_le16(fp, 2); // Channels
put_le32(fp, SAMPLE_RATE); // SampleRate
put_le32(fp, SAMPLE_RATE * 4); // BytesPerSec
put_le16(fp, 4); // Alignment (channels * bytesPerSample)
put_le16(fp, 16); // BitsPerSample
put_le16(fp, 0);
put_str(fp, "data");
put_le32(fp, lLength);
return ERR_NOERROR;
}
int WriteWaveData (long lLength, PBYTE pBuffer)
{
//FILE *fp = fopen(pcMyTmpFileName, "ab"); // append binary
//if (! fp) return ERR_CANNOTSAVE;
fwrite(pBuffer,lLength,1,fMyTmp);
//fclose(fp);
lBytesRecorded += lLength;
return ERR_NOERROR;
}
// end code for saving wav
// code for recording
DLLIM****T short __stdcall StartRecording (char * pcFileName)
{
// check status, if not playing, return
if (hWaveOut==NULL) return ERR_NOTPLAYING ; // Not able to change
while
playing
// open file with header, length set to max length (long)
lBytesRecorded=0;
FILE *fp = fopen(pcFileName, "wb"); // write binary
if (! fp) return ERR_CANNOTSAVE;
fclose (fp);
// Save the filename
strcpy (pcMyFileName, pcFileName);
tmpnam (pcMyTmpFileName);
fMyTmp = fopen(pcMyTmpFileName, "ab"); // append binary
// set bRecording
bRecording=TRUE;
return ERR_NOERROR;
}
DLLIM****T short __stdcall StopRecording ()
{
long i;
PBYTE pBufferTmp;
if (! bRecording) return ERR_NOTRECORDING;
// indicate that no more buffers should be written to the file
bRecording=FALSE;
fclose(fMyTmp);
// reopen the file and set the correct length
// have to rewrite whole file
pBufferTmp = malloc (OUT_BUFFER_SIZE) ;
FILE *fp = fopen(pcMyFileName, "wb"); // write binary
if (! fp)
{
free(pBufferTmp);
return ERR_CANNOTSAVE;
}
// save header with updated info
WriteWaveHeader (fp, lBytesRecorded) ;
// now append the tmp file to the new file
FILE *ftmpp = fopen(pcMyTmpFileName, "rb"); // read binary
for (i=0; i<(lBytesRecorded / OUT_BUFFER_SIZE); i++)
{
fread (pBufferTmp, 1, OUT_BUFFER_SIZE, ftmpp);
fwrite (pBufferTmp, 1, OUT_BUFFER_SIZE, fp);
}
fclose (ftmpp);
fclose (fp);
// clean up tmp buffer
free(pBufferTmp);
// delete tmp file
remove(pcMyTmpFileName);
return ERR_NOERROR;
}
// end code for recording
DLLIM****T short __stdcall SaveSound (char * pcFileName, double dLength)
{
if (hWaveOut!=NULL)
{
return ERR_PLAYING;
}
// Create buffer of sLength seconds long
long lNumSamples=dLength * (double) SAMPLE_RATE ;
PBYTE pBuffer;
pBuffer = malloc (lNumSamples * 4) ;
if (!pBuffer)
{
free (pBuffer) ;
return ERR_OUTOFMEMORY ;
}
FillBuffer (pBuffer, lNumSamples * 4) ;
// Save buffer to filename
ret=write_wav (pcFileName, lNumSamples * 4, pBuffer);
free (pBuffer) ;
return ret;
}
void ApplyPan (short sChannel)
{
// Set the volume value for each channel with panning
if (dMyPan[sChannel]<0) // to the left
{
dMyLRVol[0][sChannel] = dMyVol[sChannel]; // Left gets 1
always
dMyLRVol[1][sChannel] = dMyVol[sChannel] *
(1+dMyPan[sChannel]);
// Right fades down to 0
// MessageBoxPrintf ("<1","[sChannel=%d] dMyVol=%f dMyPan=%f
dMyLRVol=0:%f
1:%f",sChannel,dMyVol[sChannel],dMyPan[sChannel],dMyLRVol[0][sChannel],dMyLRVol[1][sChannel]);
} else {
dMyLRVol[0][sChannel] = dMyVol[sChannel] *
(1-dMyPan[sChannel]);
dMyLRVol[1][sChannel] = dMyVol[sChannel];
}
}
DLLIM****T short __stdcall SetAutoRange (short sAutoRange)
{
bAutoRange=(sAutoRange!=0);
return ERR_NOERROR;
}
DLLIM****T short __stdcall SetNumberOfChannels (short sChannels)
{
if (hWaveOut!=NULL) return ERR_PLAYING ; // Not able to change while
playing
if (sChannels>MAX_CH) return ERR_MAXCH ;
sMyNCh=sChannels ;
// Initiate the sound parameters with some default values
dMyMasterVol=1 ;
int i;
for (i=0; i<sMyNCh; i++)
{
dMyFreq[i]=220 + 220 * i;
dMyVol[i]=1;
dMyPan[i]=0;
dMyPhase[i]=0;
}
return 0;
}
DLLIM****T short __stdcall SetPhase (short sChannel, double dPhase)
{
if (sChannel>=0 && sChannel<sMyNCh)
{
if (dPhase<-PI) return ERR_OUTOFRANGE;
if (dPhase>PI) return ERR_OUTOFRANGE;
dMyPhase[sChannel]=dPhase;
return 0;
} else {
return ERR_MAXCH;
}
}
DLLIM****T short __stdcall SetMasterVolume (double dVolume)
{
if (dVolume<0) dVolume=0;
if (dVolume>1) dVolume=1;
dMyMasterVol=dVolume;
return 0;
}
DLLIM****T short __stdcall SetVolume (short sChannel, double dVolume)
{
if (sChannel>=0 && sChannel<sMyNCh)
{
if (dVolume<0) dVolume=0;
if (dVolume>1) dVolume=1;
dMyVol[sChannel]=dVolume;
ApplyPan(sChannel);
return ERR_NOERROR;
} else {
return ERR_MAXCH;
}
}
DLLIM****T short __stdcall SetPan (short sChannel, double dPan)
{
if (sChannel>=0 && sChannel<sMyNCh)
{
if (dPan<-1) dPan=-1;
if (dPan>1) dPan=1;
dMyPan[sChannel]=dPan;
ApplyPan(sChannel);
return ERR_NOERROR;
} else {
return ERR_MAXCH;
}
}
DLLIM****T short __stdcall SetFrequency (short sChannel, double
dFrequency)
{
if (sChannel>=0 && sChannel<sMyNCh)
{
if (dFrequency<=0) return ERR_OUTOFRANGE;
if (dFrequency>.5*SAMPLE_RATE) return ERR_OUTOFRANGE;
dMyFreq[sChannel]=PIx2 * dFrequency / SAMPLE_RATE;
return ERR_NOERROR;
} else {
return ERR_MAXCH;
}
}
DLLIM****T short __stdcall SetChannel (short sChannel, double dVolume,
double
dPan, double dFreq, double dPhase)
{
dMyFreq[sChannel]=PIx2 * dFreq / SAMPLE_RATE;
if (dVolume<0) dVolume=0;
if (dVolume>1) dVolume=1;
dMyVol[sChannel]=dVolume;
if (dPan<-1) dPan=-1;
if (dPan>1) dPan=1;
dMyPan[sChannel]=dPan;
ApplyPan(sChannel);
dMyPhase[sChannel]=dPhase;
// MessageBoxPrintf ("SecretSound.dll: SetChannel", "CH:%i VOL:%f
PAN:%f FREQ:%f PHASE:%f", sChannel, dMyVol[sChannel], dMyPan[sChannel],
dMyFreq[sChannel], dMyPhase[sChannel]);
return ERR_NOERROR;
}
DLLIM****T short __stdcall SetChannels (double dVolume[], double dPan[],
double dFreq[], double dPhase[] )
{
int i=0;
for (i=0; i<sMyNCh; i++)
{
dMyVol[i]=dVolume[i];
dMyPan[i]=dPan[i];
ApplyPan(i);
dMyFreq[i]=PIx2 * dFreq[i] / SAMPLE_RATE;
dMyPhase[i]=dPhase[i];
}
return ERR_NOERROR;
}
DLLIM****T short __stdcall StartSound ()
{
if (sMyNCh==0) return ERR_NOCHANNELS;
// Variable used to stop the sound, to notify the callback function
bClosing=FALSE;
if (hWaveOut!=NULL)
{
return ERR_PLAYING;
}
// Allocate memory for two headers and two buffers
pWaveHdr1 = malloc (sizeof (WAVEHDR)) ;
pWaveHdr2 = malloc (sizeof (WAVEHDR)) ;
pBuffer1 = malloc (OUT_BUFFER_SIZE) ;
pBuffer2 = malloc (OUT_BUFFER_SIZE) ;
if (!pWaveHdr1 || !pWaveHdr2 || !pBuffer1 || !pBuffer2)
{
if (!pWaveHdr1) free (pWaveHdr1) ;
if (!pWaveHdr2) free (pWaveHdr2) ;
if (!pBuffer1) free (pBuffer1) ;
if (!pBuffer2) free (pBuffer2) ;
return ERR_OUTOFMEMORY ;
}
// Prepare audio device
waveformat.wFormatTag = WAVE_FORMAT_PCM ;
waveformat.nChannels = 2 ;
waveformat.nSamplesPerSec = SAMPLE_RATE ;
waveformat.wBitsPerSample = 16 ;
waveformat.nBlockAlign = waveformat.nChannels *
waveformat.wBitsPerSample / 8 ;
waveformat.nAvgBytesPerSec = waveformat.nBlockAlign *
waveformat.nSamplesPerSec ;
waveformat.cbSize = 0 ;
if (waveOutOpen (&hWaveOut, WAVE_MAPPER, &waveformat,
(DWORD) MyWaveOutProc, 0, CALLBACK_FUNCTION) !=
MMSYSERR_NOERROR)
{ // Soundcard buzy or not present
free (pWaveHdr1) ;
free (pWaveHdr2) ;
free (pBuffer1) ;
free (pBuffer2) ;
return ERR_DEVICENOTREADY ;
}
// Initiate header and prepare
// TODO: Additional error checking...
pWaveHdr1->lpData = pBuffer1 ;
pWaveHdr1->dwBufferLength = OUT_BUFFER_SIZE;
pWaveHdr1->dwBytesRecorded = 0 ;
pWaveHdr1->dwUser = 0 ;
pWaveHdr1->dwFlags = 0 ;
pWaveHdr1->dwLoops = 1 ;
pWaveHdr1->lpNext = NULL ;
pWaveHdr1->reserved = 0 ;
ret=waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
pWaveHdr2->lpData = pBuffer2 ;
pWaveHdr2->dwBufferLength = OUT_BUFFER_SIZE;
pWaveHdr2->dwBytesRecorded = 0 ;
pWaveHdr2->dwUser = 0 ;
pWaveHdr2->dwFlags = 0 ;
pWaveHdr2->dwLoops = 1 ;
pWaveHdr2->lpNext = NULL ;
pWaveHdr2->reserved = 0 ;
ret=waveOutPrepareHeader (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ;
// Load two Buffers to audio device
FillBuffer (pBuffer1, OUT_BUFFER_SIZE) ;
ret=waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
FillBuffer (pBuffer2, OUT_BUFFER_SIZE) ;
ret=waveOutWrite (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ;
return 0;
}
DLLIM****T short __stdcall StopSound ()
{
bClosing=TRUE;
do
ret=waveOutClose (hWaveOut) ;
while (ret==WAVERR_STILLPLAYING) ;
return 0;
}
void CALLBACK MyWaveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
switch (uMsg) {
case WOM_OPEN:
break;
case WOM_DONE:
// Puffer erneut füllen und an Audio-Gerät übergeben
if (bClosing) {
// Do not send any new buffers
return;
}
FillBuffer (((PWAVEHDR) dwParam1)->lpData, OUT_BUFFER_SIZE) ;
ret=waveOutWrite (hWaveOut, (PWAVEHDR) dwParam1, sizeof
(WAVEHDR))
;
break;
case WOM_CLOSE:
// if we were recording, stop recording and close file
if (bRecording)
{
ret = StopRecording ();
}
ret=waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof
(WAVEHDR)) ;
if (TRUE || ret==MMSYSERR_NOERROR )
{
free (pWaveHdr1) ;
free (pBuffer1) ;
}
ret=waveOutUnprepareHeader (hWaveOut, pWaveHdr2, sizeof
(WAVEHDR)) ;
if (TRUE || ret==MMSYSERR_NOERROR )
{
free (pWaveHdr2) ;
free (pBuffer2) ;
}
ret=waveOutReset (hWaveOut) ;
hWaveOut=NULL;
}
}
DLLIM****T short __stdcall MyFFT (long lNin, double dInArray[], long lNout,
double dOutArray[], double dFromHz, double dToHz, double dResolution,
double
dSampleRate)
{
long i,j ;
double d, f, s, z ;
double re[lNout] ;
double im[lNout] ;
s = 0;
for (i = 0; i<lNout; i++)
{
d = i * dResolution + dFromHz;
re[i] = 0;
im[i] = 0;
f = (d * 2 * PI) / dSampleRate;
for (j = 0; j<lNin; j++)
{
z = j * f;
re[i] += dInArray[j] * sin(z);
im[i] += dInArray[j] * cos(z);
}
dOutArray[i] = 2* sqrt(re[i] * re[i] + im[i] * im[i]);
}
return 0;
}


|