I want to create a dll that I can use in Visual Basic. The dll should generate custom sounds live of which I provide the frequencies, volumes and phases. I am trying to do this with the waveOutOpen call. The sound is 44100 Hz, stereo.

I created these functions to interface with VB:

DLLIMPORT short __stdcall SetPhase (short Channel, double Phase);
DLLIMPORT short __stdcall SetMasterVolume (double Volume);
DLLIMPORT short __stdcall SetVolume (short Channel,double Volume);
DLLIMPORT short __stdcall SetFrequency (short Channel,double Frequency);
DLLIMPORT short __stdcall StartSound (double MasterVolume, short NChannels, double Frequencies[], double Volumes[], double Phases[]);
DLLIMPORT short __stdcall StopSound ();

and the callback function:

void CALLBACK MyWaveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) ;

The StartSound function should take care of initialising the audio device and starting the callback function.
StopSound should terminate the callback calling.

The other functions just change the global variables for the various channels. (A channel is a sound of one frequency.)

Here is part of my code:


Code:
DLLIMPORT short __stdcall StartSound  (double MasterVolume, short NChannels, double Frequencies[], double Volumes[], double Phases[])
{
   // Variable used to stop the sound, to notify the callback function
    bShutOff=FALSE;

    SetMasterVolume (MasterVolume);

    // Check and set the number of requested channels
    if (NChannels<1 || NChannels>=MAX_CH) return -2;
    siNChannels = NChannels;

    // Initialise the global variables
    short i;
    for (i=0; i<siNChannels; i++)
        {
            SetFrequency (i, Frequencies[i]);
            SetVolume (i, Volumes[i]);
            SetPhase (i, Phases[i]);
        }

    if (hWaveOut!=NULL) waveOutReset (hWaveOut) ; // reset device when already open

    // Speicher anfordern für 2 Header und 2 Puffer
    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) ;

         MessageBeep (MB_ICONEXCLAMATION) ;
         MessageBox (NULL, TEXT ("Not enough memory!"),
                     TEXT ("SecretSound.dll"), MB_ICONEXCLAMATION | MB_OK) ;
         return TRUE ;
    }

    // Audio-Gerät für Ausgabe vorbereiten
    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)
    {    // Soundkarte besetzt oder nicht vorhanden

         free (pWaveHdr1) ;
         free (pWaveHdr2) ;
         free (pBuffer1) ;
         free (pBuffer2) ;

         hWaveOut = NULL ;
         MessageBeep (MB_ICONEXCLAMATION) ;
         MessageBox (NULL,
              TEXT ("Error occured while opening audio device!"),
              TEXT ("SecretSound.dll"), MB_ICONEXCLAMATION | MB_OK) ;
         return TRUE ;
    }


    // Header initialisieren und vorbereiten
    pWaveHdr1->lpData          = pBuffer1 ;
    pWaveHdr1->dwBufferLength  = OUT_BUFFER_SIZE;
    pWaveHdr1->dwBytesRecorded = 0 ;
    pWaveHdr1->dwUser          = 0 ;
    pWaveHdr1->dwFlags         = 0 ;
    pWaveHdr1->dwLoops         = 0 ;
    pWaveHdr1->lpNext          = NULL ;
    pWaveHdr1->reserved        = 0 ;

    ret=waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
    ShowError (ret, TEXT("waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR))"));

    pWaveHdr2->lpData          = pBuffer2 ;
    pWaveHdr2->dwBufferLength  = OUT_BUFFER_SIZE;
    pWaveHdr2->dwBytesRecorded = 0 ;
    pWaveHdr2->dwUser          = 0 ;
    pWaveHdr2->dwFlags         = 0 ;
    pWaveHdr2->dwLoops         = 0 ;
    pWaveHdr2->lpNext          = NULL ;
    pWaveHdr2->reserved        = 0 ;

    ret=waveOutPrepareHeader (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ;
    ShowError (ret, TEXT("waveOutPrepareHeader (hWaveOut, pWaveHdr2, sizeof (WAVEHDR))"));

    // Zwei Pufferinhalte an Audio-Gerät übergeben
    FillBuffer (pBuffer1) ;
    ret=waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
    ShowError (ret, TEXT("waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR))"));

    FillBuffer (pBuffer2) ;
    ret=waveOutWrite (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ;
    ShowError (ret, TEXT("waveOutWrite (hWaveOut, pWaveHdr2, sizeof (WAVEHDR))"));

    return 0;
}

DLLIMPORT short __stdcall StopSound  ()
{
    if (hWaveOut!=NULL)
    {
        DebugPrint (1,"Stop",TEXT("StopSound"));
        ret=waveOutClose (hWaveOut) ;
        ShowError (ret,TEXT("waveOutClose (hWaveOut)"));



        DebugPrint (2,"Stop",TEXT("StopSound"));
        if (ret==0)
        {
            ret=waveOutReset (hWaveOut) ;
            ShowError (ret, TEXT("waveOutReset (hWaveOut)"));
        }
        DebugPrint (3,"Stop",TEXT("StopSound"));
        hWaveOut=NULL;
    }
    return 0;
}



void CALLBACK MyWaveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{

     switch (uMsg)
     {
     case MM_WOM_OPEN:  // diese Nachricht folgt auf den Aufruf waveOutOpen
          return;

     case MM_WOM_DONE:     // Puffer abgespielt

          // Puffer erneut füllen und an Audio-Gerät übergeben
          FillBuffer (((PWAVEHDR) dwParam1)->lpData) ;
          ret=waveOutWrite (hWaveOut, (PWAVEHDR) dwParam1, sizeof (WAVEHDR)) ;
          ShowError (ret, TEXT(""));
          return;

     case MM_WOM_CLOSE:    // Reaktion auf waveOutReset

            ret=waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
            ShowError (ret, TEXT("waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR))"));
            if (ret==0)
            {
                free (pWaveHdr1) ;
                free (pBuffer1) ;
            }

            ret=waveOutUnprepareHeader (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ;
            ShowError (ret, TEXT("waveOutUnprepareHeader (hWaveOut, pWaveHdr2, sizeof (WAVEHDR))"));
            if (ret==0)
            {
                free (pWaveHdr2) ;
                free (pBuffer2) ;
            }

            MessageBox (NULL, TEXT ("MM_WOM_CLOSE"),
                                     TEXT ("SecretSound.dll"), MB_ICONEXCLAMATION | MB_OK) ;

          return;
     }
}
I have been staring at it for days, but I can not get any clou as to what I am doing wrong (or right ;-)

Some advice would be highly appreciated!