Affe007
Lt. Commander
- Registriert
- März 2004
- Beiträge
- 1.462
Moinsen ich hab einige Probleme mit C++ und DirectSound. Was will ich überhaupt machen?
Ich habe vor ein Prog zu schreiben, was den Mic-Eingang aufnimmt, zwischenspeichert und dann wieder ausgibt. (Später einmal soll noch eine FFT und eine Ausgabe hinzukommen aber alles zu seiner Zeit )
Da ist jetzt nicht sooo der C++ Held bin und mit DS noch nie in Berührung gekommen bin, haben sich da einige Probleme ergeben
Was hab ich hin bekommen:
- Sound Device (Capture Render) erstellt
- Buffer konfiguriert und erstellt
- das Häppchenweise capturen sollte auch funktionieren
Aber jetzt zu meinen Probs, ich benutze z.Z. die Buffer so, dass ich immer das auslese/schreibe was gerade so neu drin ist (ohne Benachrichtigungen). Zwar hab ich gerafft wie ich die Notifications erstelle (dank Code Beispiel aus der Hilfe) allerdings hab ich kein Plan wie ich auf die Events reagieren kann. (Threads erstellen, WaitForMultipleEvents usw. Buch mit 3263 Siegeln)
Wie den auch sei, das Häppchenweise auslesen des Capture Buffers funktioniert (glaub ich) aber das schreiben des Render Buffers leider nicht Ich hab auh langsam keine Ideen mehr.
So vll. kann mir einer zeigen wie ich das Prog so hinbiege, dass es einen Stream aufnimmt, kurz zwischenspeichert und dann wieder den Stream ausgibt.
Was noch besser wäre, wenn mir einer die Notificationen erklären könnte
So hier das Unglück, ich hoffe die ganzen Programmierer drehen jetzt nicht gleich durch, wie scheisse das doch alles is
Ich habe vor ein Prog zu schreiben, was den Mic-Eingang aufnimmt, zwischenspeichert und dann wieder ausgibt. (Später einmal soll noch eine FFT und eine Ausgabe hinzukommen aber alles zu seiner Zeit )
Da ist jetzt nicht sooo der C++ Held bin und mit DS noch nie in Berührung gekommen bin, haben sich da einige Probleme ergeben
Was hab ich hin bekommen:
- Sound Device (Capture Render) erstellt
- Buffer konfiguriert und erstellt
- das Häppchenweise capturen sollte auch funktionieren
Aber jetzt zu meinen Probs, ich benutze z.Z. die Buffer so, dass ich immer das auslese/schreibe was gerade so neu drin ist (ohne Benachrichtigungen). Zwar hab ich gerafft wie ich die Notifications erstelle (dank Code Beispiel aus der Hilfe) allerdings hab ich kein Plan wie ich auf die Events reagieren kann. (Threads erstellen, WaitForMultipleEvents usw. Buch mit 3263 Siegeln)
Wie den auch sei, das Häppchenweise auslesen des Capture Buffers funktioniert (glaub ich) aber das schreiben des Render Buffers leider nicht Ich hab auh langsam keine Ideen mehr.
So vll. kann mir einer zeigen wie ich das Prog so hinbiege, dass es einen Stream aufnimmt, kurz zwischenspeichert und dann wieder den Stream ausgibt.
Was noch besser wäre, wenn mir einer die Notificationen erklären könnte
So hier das Unglück, ich hoffe die ganzen Programmierer drehen jetzt nicht gleich durch, wie scheisse das doch alles is
Code:
#include <dsound.h>
#include <windows.h>
#include <iostream>
using namespace std;
// Handle des aktiven Consolen Fensters
HWND GetConsoleHwnd(void){
LPCWSTR newtitle = (LPCWSTR) L"SDR-Test";
SetConsoleTitle(newtitle);
Sleep(40);
return(FindWindow(NULL, newtitle));
}
// setzen der WaveFormatEx Eigenschaften
void SetWaveFormatEx(WAVEFORMATEX *wfx){
memset(wfx, 0, sizeof(WAVEFORMATEX));
wfx->wFormatTag = WAVE_FORMAT_PCM;
wfx->nChannels = 2;
wfx->wBitsPerSample = 16;
wfx->nSamplesPerSec = 44100;
wfx->nBlockAlign = wfx->wBitsPerSample * wfx->nChannels / 8;
wfx->nAvgBytesPerSec = wfx->nSamplesPerSec * wfx->nBlockAlign;
}
// setzen der Capture und Render Buffer Eigenschaften
void SetCRBufferDescribtion(DSCBUFFERDESC *dscbdesc, DSBUFFERDESC *dsbdesc, WAVEFORMATEX *wfx){
// Capture
memset (dscbdesc, 0, sizeof(DSCBUFFERDESC));
dscbdesc->dwSize = sizeof(DSCBUFFERDESC);
dscbdesc->dwFlags = 0;
dscbdesc->dwBufferBytes = wfx->nSamplesPerSec;
dscbdesc->lpwfxFormat = wfx;
dscbdesc->dwFXCount = 0;
dscbdesc->lpDSCFXDesc = NULL;
// Render
memset (dsbdesc, 0, sizeof(DSBUFFERDESC));
dsbdesc->dwSize = sizeof(DSBUFFERDESC);
dsbdesc->dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
dsbdesc->dwBufferBytes = wfx->nSamplesPerSec;
dsbdesc->lpwfxFormat = wfx;
}
int main(int argc, char* argv[]){
HWND CMDWHandle; // CMD Fenster Handl
HRESULT hr; // Fehlercode
LPDIRECTSOUNDFULLDUPLEX lpdsFullDuplex; // DirectSound Full Duplex Interface
LPDIRECTSOUNDCAPTUREBUFFER8 lpdsCaptureBuffer; // DirectSound Capture Buffer Interface
LPDIRECTSOUNDBUFFER8 lpdsRenderBuffer; // DirectSound Render Buffer Interface
WAVEFORMATEX WaveFormatEx; // Format der Wave Audio Daten
DSCBUFFERDESC DSCBufferDesc; // Eigenschaften des Capture Buffers
DSBUFFERDESC DSBufferDesc; // Eigenschaften des Render Buffers
// Handle des aktiven Consolen Fensters
CMDWHandle = GetConsoleHwnd();
// setzen der WaveFormatEx Eigenschaften
SetWaveFormatEx(&WaveFormatEx);
// setzen der Capture und Render Buffer Eigenschaften
SetCRBufferDescribtion(&DSCBufferDesc, &DSBufferDesc, &WaveFormatEx);
// erstellen des DirectSound Full Duplex Device und der Buffer
hr = DirectSoundFullDuplexCreate8(
NULL,
NULL,
&DSCBufferDesc,
&DSBufferDesc,
CMDWHandle,
DSSCL_PRIORITY,
&lpdsFullDuplex,
&lpdsCaptureBuffer,
&lpdsRenderBuffer,
NULL);
if(FAILED(hr)){
cout << "Full Duplex Device " << hr << endl;
}
// Capture Buffer starten
hr = lpdsCaptureBuffer->Start(DSCBSTART_LOOPING);
if(FAILED(hr)){
cout << "Aufnahme Start " << hr << endl;
}
// Play Cursor auf 0 setzten
hr = lpdsRenderBuffer->SetCurrentPosition(0);
if(FAILED(hr)){
cout << "Wiedergabe Position " << hr << endl;
}
// Play
hr = lpdsRenderBuffer->Play(0, 0, 0);
if(FAILED(hr)){
cout << "Wiedergabe " << hr << endl;
}
LPVOID lpvRead1, lpvRead2, lpvWrite1, lpvWrite2;
DWORD dwLength1 = 0, dwLength2 = 0;
DWORD dwReadCursor = 0, dwLockSize = 0, dwLastReadCursor = 0;
DWORD dwWriteCursor, dwPlayCursor, dwOffset = 0;
DWORD pbData[44100];
while(1){
Sleep(45); // warten bis einige Daten geladen sind
/********************************/
/* Capture */
/********************************/
// Poition des Read Cursors abfragen
hr = lpdsCaptureBuffer->GetCurrentPosition(NULL, &dwReadCursor);
if(FAILED(hr)){
cout << "Capture Buffer Position " << hr << endl;
}
// Grösse des Locks bestimmen
if(dwReadCursor < dwLastReadCursor){
dwLockSize = dwLastReadCursor - dwReadCursor;
}
else{
dwLockSize = dwReadCursor - dwLastReadCursor;
}
// Capture Buffer sperren
hr = lpdsCaptureBuffer->Lock(
dwLastReadCursor, // Offset at which to start lock.
dwLockSize, // Size of lock.
&lpvRead1, // Gets address of first part of lock.
&dwLength1, // Gets size of first part of lock.
&lpvRead2, // Address of wraparound not needed.
&dwLength2, // Size of wraparound not needed.
0); // Flag.
// gesperrter Teil des Capture Buffer wird gespeichert
if(SUCCEEDED(hr)){
memcpy(pbData, lpvRead1, dwLength1);
if(lpvRead2 != NULL){
memcpy(pbData + dwLength1, lpvRead2, dwLength2);
}
// Capture Buffer freigeben
lpdsCaptureBuffer->Unlock(
lpvRead1, // Address of lock start.
dwLength1, // Size of lock.
lpvRead2, // No wraparound portion.
dwLength2); // No wraparound size.
dwLastReadCursor = dwReadCursor; // ReadCursor Position speichern
}
else{
cout << "Capture Buffer Lock " << hr << endl;
}
/********************************/
/* Render */
/********************************/
// Positionen der Capture und Write Cursor abfragen
hr = lpdsRenderBuffer->GetCurrentPosition(&dwPlayCursor,&dwWriteCursor);
if(FAILED(hr)){
cout << "Render Buffer Position " << hr << endl;
}
hr = lpdsRenderBuffer->Lock(
dwOffset, // Offset at which to start lock.
dwLockSize, // Size of lock.
&lpvWrite1, // Gets address of first part of lock.
&dwLength1, // Gets size of first part of lock.
&lpvWrite2, // Address of wraparound not needed.
&dwLength2, // Size of wraparound not needed.
0); // Flag.
// schreiben in den gesperrten Teil des Render Buffers
if (SUCCEEDED(hr)){
memcpy(lpvWrite1, pbData, dwLength1);
if(lpvWrite2 != NULL){
memcpy(lpvWrite2, pbData + dwLength1, dwLength2);
}
// Render Buffer freigeben
lpdsRenderBuffer->Unlock(
lpvWrite1, // Address of lock start.
dwLength1, // Size of lock.
lpvWrite2, // No wraparound portion.
dwLength2); // No wraparound size.
// Offset ermitteln ???
if((dwOffset + dwLockSize) > 40099){
dwOffset = dwOffset + dwLockSize - 40999;
}
else{
dwOffset = dwOffset + dwLockSize;
}
}
else{
cout << "Render Buffer Lock " << hex << hr << endl;
}
}
system("PAUSE");
lpdsRenderBuffer->Stop();
lpdsRenderBuffer->Release();
lpdsCaptureBuffer->Stop();
lpdsCaptureBuffer->Release();
lpdsFullDuplex->Release();
return(0);
}
Zuletzt bearbeitet: