在Win32

时间:2016-11-20 00:02:00

标签: c# c++ winapi audio dll

我有这个学校作业,我们需要根据一些Win32声音播放器/录音机制作DLL,然后将它绑定到我们已经制作的编辑声音文件的C#应用​​程序中。我有它,所以如果你用DLL记录它将录制的声音文件放入主程序使用Marshal.Copy将DLL中的非托管byte []复制到主程序中的托管byte [],然后将值转换为短裤,效果很好。但是,我也想反过来。也就是说,我希望能够将一个byte []传递给要播放的DLL,因为它当前只播放它录制的声音。我查看了Marshal类的文档并没有找到任何有用的东西,所以我不知道如何去做。到目前为止,这个程序非常庞大,所以我将尝试仅发布相关代码。我在DLL中的设置使用一个不可见的CallBack窗口,该窗口处理由DLL外部调用的函数发送的WIM和WOM消息。

主程序:

    [DllImport("RecordDll.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr getBytes();

    [DllImport("RecordDll.dll", CharSet = CharSet.Auto)]
    public static extern int getNumBytes();

    //I thought I could use something like this to set it
    [DllImport("RecordDll.dll", CharSet = CharSet.Auto)]
    public static extern void setBytes(IntPtr wav);

    short[] storedRecording;

    //Constructor plus a ton of other irrelevant stuff here

    private void RecordStart_Click(object sender, EventArgs e){
        RecordStart.Enabled = false;
        PlayStart.Enabled = false;
        Stop.Enabled = true;
        Stop.Focus();
        RecordStatus.Text = "";
        recordStart(); //DLL function
    }

    private void StopRecord_Click(object sender, EventArgs e){
        recordEnd(); //DLL function
        int numBytes = getNumBytes();
        byte[] byteArr = new Byte[numBytes];
        storedRecording = new short[numBytes];
        Marshal.Copy(getBytes(), byteArr, 0, numBytes);
        for (int i = 0; i < numBytes; i++)
        {
            storedRecording[i] = byteArr[i];
        }
        RecordStatus.Text = "Recording loaded.";
    }

    private void PlayStart_Click(object sender, EventArgs e){
        PlayStart.Enabled = false;
        PlayPause.Enabled = true;
        Stop.Enabled = true;
        Stop.Focus();
        RecordStatus.Text = "";
        if(storedRecording != null){
            //convert the array to an unmanaged byte[] somehow?
            //then call setBytes with that byte[]?
        }
        playBegin(); //DLL function
    }

记录/播放DLL中的相关功能:

    static PBYTE* pSaveBuffer;

    __declspec(dllexport) BOOL CALLBACK playBegin() {
        // Open waveform audio for output

        waveform.wFormatTag = WAVE_FORMAT_PCM;
        waveform.nChannels = 1;
        waveform.nSamplesPerSec = 11025;
        waveform.nAvgBytesPerSec = 11025;
        waveform.nBlockAlign = 1;
        waveform.wBitsPerSample = 8;
        waveform.cbSize = 0;

        if (waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveform,
            (DWORD)myHwnd, 0, CALLBACK_WINDOW))
        {
            MessageBeep(MB_ICONEXCLAMATION);
            MessageBox(myHwnd, szOpenError, szAppName,
                MB_ICONEXCLAMATION | MB_OK);
        }
        return TRUE;
    }

    __declspec(dllexport) PBYTE* CALLBACK getBytes() {
        return pSaveBuffer;
    }

    __declspec(dllexport) int CALLBACK getNumBytes() {
        return dwDataLength;
    }

用于处理发送到DLL中的CallbackWindow的waveOutOpen消息的WinProc:

case MM_WOM_OPEN:
        // Set up header

        pWaveHdr1->lpData = (LPSTR)*pSaveBuffer;
        pWaveHdr1->dwBufferLength = dwDataLength;
        pWaveHdr1->dwBytesRecorded = 0;
        pWaveHdr1->dwUser = 0;
        pWaveHdr1->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
        pWaveHdr1->dwLoops = dwRepetitions;
        pWaveHdr1->lpNext = NULL;
        pWaveHdr1->reserved = 0;

        // Prepare and write

        waveOutPrepareHeader(hWaveOut, pWaveHdr1, sizeof(WAVEHDR));
        waveOutWrite(hWaveOut, pWaveHdr1, sizeof(WAVEHDR));

        bEnding = FALSE;
        bPlaying = TRUE;
        return 0;

希望能够传达它的工作方式。尽管代码量很大,但我很确定这个问题很小。我只需要能够设置* pSaveBuffer来包含主程序中的数据。我有一种感觉,这可以通过将托管数组转换为非托管数组来完成,但就像我说我不知道​​这是否可能。任何有关此问题的帮助将不胜感激!

0 个答案:

没有答案