Servo Ansteuerung per Soundkarte
-
Hallo,
ich bin beim googeln auf dieses schöne Forum gestoßen und hätte ein kleines Problem. Ich würde gerne ein kleines Programm schreiben mit dem ich einen kleinen Elektro Servo über die Soundkarte ansteuern kann. Dazu wollte ich die dsound.h aus der DirectX SDK verwenden, da es hier möglich ist den Buffer selbst zu füllen. Dazu habe ich erstmal einen kleinen Code geschrieben, der mir ein Sinus-Signal generiert und ausgeben soll.#include <dsound.h> #include <math.h> #include <conio.h> #include <stdio.h> //Einstellungen #define Volume 50 #define Frequenz 100 //Variablen Deklaration LPDIRECTSOUND lpDirectSound = NULL; LPDIRECTSOUNDBUFFER lpDirectSoundBuffer = NULL; WAVEFORMATEX waveFormatEx = {0}; DSBUFFERDESC dsBufferDesc = {0}; int Size; void* data; HRESULT hr; void main() { //DirectSound Initialisierung hr = DirectSoundCreate(NULL, &lpDirectSound, NULL); if(hr != S_OK) printf("DirectSound fehler \n"); //Signal erstellen int f = 44100/Frequenz; Size = f; data = VirtualAlloc(NULL, Size, MEM_COMMIT, PAGE_READWRITE); for(int i = 0; i<f; i++) *((short*) data + i) = (short)(sin(((double)i/(double)f)*6.283185)*32767.0); //Statischen Buffer anlegen if(lpDirectSoundBuffer != NULL) lpDirectSoundBuffer->Release(); waveFormatEx.wFormatTag= WAVE_FORMAT_PCM; waveFormatEx.nBlockAlign = 1; waveFormatEx.nChannels = 1; waveFormatEx.nSamplesPerSec = 44100; waveFormatEx.wBitsPerSample = 8; waveFormatEx.nAvgBytesPerSec = 44100; dsBufferDesc.dwFlags= /*DSBCAPS_PRIMARYBUFFER |*/ DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME |DSBCAPS_GLOBALFOCUS; dsBufferDesc.dwSize = sizeof(dsBufferDesc); dsBufferDesc.dwBufferBytes= Size; dsBufferDesc.lpwfxFormat = &waveFormatEx; dsBufferDesc.dwReserved = 0; hr = lpDirectSound->CreateSoundBuffer(&dsBufferDesc, &lpDirectSoundBuffer, NULL); if(hr != DS_OK) printf("CreateSoundBuffer \n"); //Lautstärke einstellen int v = DSBVOLUME_MIN + (int) (((double) Volume / 100.0) * (double) (DSBVOLUME_MAX - DSBVOLUME_MIN)*37); // lpDirectSoundBuffer->SetVolume(v); //Buffer füllen void *audioPtr1,*audioPtr2; DWORD audioBytes1, audioBytes2; hr = lpDirectSoundBuffer->Lock(0,0, &audioPtr1, &audioBytes1, &audioPtr2, &audioBytes2, DSBLOCK_ENTIREBUFFER); if(hr != DS_OK) printf("Lock \n"); CopyMemory(audioPtr1, data, Size); hr = lpDirectSoundBuffer->Unlock(audioPtr1,Size,audioPtr2,0); if(hr != DS_OK) printf("Unlock \n"); //Buffer abspielen hr = lpDirectSoundBuffer->SetCurrentPosition(0); if(hr!=DS_OK) printf("SetCurrentPos \n"); hr = lpDirectSoundBuffer->Play(0,0,DSBPLAY_LOOPING); if(hr != DS_OK) printf("Play \n"); //Warten bis Taste gedrückt _getch(); }
Allerdings gibt mir das Programm keinen Sound aus. Daraufhin habe ich mir die Rückgabewerte alle angeschaut und bei Play wird mir anstelle von DS_OK folgender Zahlenwert zurückgeliefert: -2005401530
Kann mir hier evt. jemand helfen?
Seh vermutlich den Wald vor lauter Bäumen nicht...
Schöne Grüße.
-
du wirst verstehen dass wir hier nicht die ganzen fehlercodes auswendig kennen. was bedeutet denn der fehler laut doku?
-
Habe mal den Teil zu Play für den Rückgabewert aus der Doku kopiert:
Return Value
If the method succeeds, the return value is DS_OK. If the method fails, the return value may be one of the following error values:Return code
DSERR_BUFFERLOST
DSERR_INVALIDCALL
DSERR_INVALIDPARAM
DSERR_PRIOLEVELNEEDED
-
Und welcher dieser Werte ist es?
-
erst ein mal ein paar wenige korrekturen am rande des fehlers...
verwende anstatt
void main()
int main() // laut standard muss main() einen integer zurück liefern
dekliniere variablen bitte am anfang des programmes und nicht mitten drinn, nur so ein kleiner tipp...
mit was hast du die rückgabewerte angesehen? kenne mich mit directX SDK nich wirklich aus aber normalerweise sollte es ja eine art GetError() funktion geben.
weil wenn du die rückgabe in einen int gespeichert und mit printf() ausgegeben hast ist klar das da nicht DSERR_BUFFERLOST oder ähnliches dabei raus kommt...(nich hauen wenns nich so is
)
[vergiss das mit den variablen, gequallter misst von mir in diesem beispiel xD]
-
Also, der Rückgabewert wird bei mir in
HRESULT hr;
gespeichert und besitzt beim debuggen an der Stelle den Wert -2005401530 der ja gar nicht als Rückgabewert in der Doku angegeben wird....
-
switch (hr) { case DSERR_BUFFERLOST: printf("The buffer memory has been lost and must be restored.\n"); break; case DSERR_INVALIDCALL: printf("This function is not valid for the current state of this object.\n"); break; case DSERR_INVALIDPARAM: printf("An invalid parameter was passed to the returning function\n"); break; case DSERR_PRIOLEVELNEEDED: printf("A cooperative level of DSSCL_PRIORITY or higher is required\n"); break; }
Gut Schuß
VuuRWerK
-
schon klar, aber wenn hr keinen der werte an nimmt sondern so einen komischen Zahlen Wert, bringt mir die switch case auch nichts...
-
o.O
Schonmal mit WinAPI programmiert? Scheinbar nicht. Hast Du das switch-case mal ausprobiert? Scheinbar nicht.
Gut Schuß
VuuRWerK
-
so nochmal,
mithr = lpDirectSoundBuffer->SetCurrentPosition(0);
schreibe ich doch den Rückgabe wert in hr sprich es sollte dann da wenn alles gut läuft DS_OK drin stehen, allerdings steht dort dann nicht DS_OK buw einer der anderern Vorgegebenen Rückgabewerte sondern der komische Zahlenwert sprich die switch case würde nicht funktionieren oder?
-
5chn1tzel schrieb:
so nochmal,
mithr = lpDirectSoundBuffer->SetCurrentPosition(0);
schreibe ich doch den Rückgabe wert in hr sprich es sollte dann da wenn alles gut läuft DS_OK drin stehen, allerdings steht dort dann nicht DS_OK buw einer der anderern Vorgegebenen Rückgabewerte sondern der komische Zahlenwert sprich die switch case würde nicht funktionieren oder?
Bevor du hier weiter programmierst, eigne dir erstmal dir Grundlagen an. DS_OK und alle anderen "komischen Werte" sind einfach nur Makros...
-
HRESULT ist ein typedef auf int. DS_OK ist ein Macro (#define) mit dem Wert 0x0. D.h. Dein Code würde wie folgt aussehen wenn wir nur den Präprozessor drüber laufen lassen würden und nur den Teil vom Kompiler der die typedefs "auflöst":
int hr; hr = lpDirectSoundBuffer->SetCurrentPosition(0); if (hr == 0x0/* dezimal: 0*/)
Die anderen 4 Rückgabewerte die die Funktion Play zurück gibt sind ebenfalls nur integer werte, nur für den Programmierer vereinfacht wurde diese integer-Werte "benannt", eben in form eines Macros.
Wenn Du genügend C/C++ Kenntnisse hast (wobei hier jede andere Programmiersprache die switch-case unterstützt ebenfalls ausreichen sollte) wirst Du wissen das man, mithilfe von switch-case, verschiedene integegrale werte "auswerten" kann, switch-case kann man sich u.a. wie Sprungmarken(Labels) in Assembler vorstellen.
Und wenn Du jetzt alles kombinierst wirst Du feststellen das anstelle der Macros im kompilierten Code die integer-werte stehen werden, und nicht wie Du wahrschienlich denkst die benannten "Symbole".Ich gehe also immernoch davon aus das Du das switch-case nicht gestestet hast, was mir eigentlich obigen Roman hätte erspart ...
Gut Schuß
VuuRWerK
-
okay, danke jetzt hab ich auch verstanden, was du meinst sry da hatte ich nicht dran gedacht... es liefert A cooperative level of DSSCL_PRIORITY or higher is required
-
Na dann ... Der Fehler sagt es Dir ja schon was Du machen musst, dann probier das doch einfach mal aus.
Gut Schuß
VuuRWerK