我有这个学校作业,我们需要根据一些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来包含主程序中的数据。我有一种感觉,这可以通过将托管数组转换为非托管数组来完成,但就像我说我不知道这是否可能。任何有关此问题的帮助将不胜感激!