none
Audiodaten von speziellen USB-Audio Interfaces einlesen RRS feed

  • Frage

  • Hallo Forum

    Wir sind am Überlegen, ob wir nicht die Geräusche einer Maschine zur Zustandsbeurteilung einlesen und auswerten wollen. Da die derzeit erhältlichen USB-Audio Interfaces mittlerweile sehr günstig geworden sind, möchten wir so etwas verwenden.

    Diese Dinger können aber im Gegensatz zu normalen Audio-Eingängen viel höhere Auflösungen und Sampleraten (zumeist 192kHz bei 24Bit). Behandelt man diese programmtechnisch genau so wie herkömmliche Soundkarten, oder gibt's da etwas zu beachten?

    Hat jemand Erfahrung mit solchen Dingern? Gibt es welche, die nicht, oder nicht in klassischer Weise zu behandeln sind?

    Welche API-Funktionen sind zum Einlesen zu empfehlen (ich denke es wird irgendeine Art von Ping-Pong Speicher sein)?

    Grüße

    FireHeart

    Freitag, 3. Juli 2015 06:45

Alle Antworten

  • Nun wenn der USB Schnöpel eine normale Soundkarte ist, dann sollte das Teil auch über die üblichen Win32 API Sound Geschichten nutzbar sein.

    Hier einmal ein wie ich finde schönes Beispiel der möglichen Nutzung:

    http://www.relisoft.com/freeware/recorder.html

    Inwieweit die Windows API jetzt 24 Bit unterstützt weiß ich allerding nicht. Ich hatte mal eine Soundkarte mit den klassischen 44.1kHz und 16 Bit mit der Windows API unterm eine Fittiche genommen gehabt.

    Hier noch ein paar weitere Quellen:

    http://www.dreamincode.net/forums/topic/208153-sound-recorder-using-the-low-level-windows-api-in-c/

    http://vismod.media.mit.edu/vismod/demos/speechcom/AudioCapture.txt


    Best regards

    Bordon

    Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.

    Dienstag, 7. Juli 2015 05:25
  • Hallo Bordon

    Also ich hab mich jetzt mal bei der MSDN über DirectSound eingelesen und Folgendes geschrieben:

            hr = DirectSoundCaptureCreate8(NULL,&pIDS,NULL);
    	if (hr == DS_OK) {
    		DSCCAPS caps;
    		caps.dwSize = sizeof(caps);
    		hr = pIDS->GetCaps(&caps);
    		if (hr == DS_OK) {
    			
    			TRACE("number of channels: %i\n",caps.dwChannels);
    			TRACE("Formats: %X\n",caps.dwFormats);
    			DSCBUFFERDESC dscbd;
    			LPDIRECTSOUNDCAPTUREBUFFER pDSCB;
    			WAVEFORMATEX               wfx;
    			wfx.wFormatTag     = WAVE_FORMAT_PCM;
    			wfx.nChannels      = 2;
    			wfx.nSamplesPerSec = 192000;
    			wfx.wBitsPerSample = 16;
    			wfx.nAvgBytesPerSec= wfx.nChannels*wfx.nSamplesPerSec*((wfx.wBitsPerSample-1)/8+1);
    			wfx.nBlockAlign    = 4;
    			wfx.cbSize         = 0;
    			dscbd.dwSize       = sizeof(DSCBUFFERDESC);
    			dscbd.dwFlags      = 0;
    			dscbd.dwBufferBytes= wfx.nAvgBytesPerSec;
    			dscbd.dwReserved   = 0;
    			dscbd.lpwfxFormat  = &wfx;
    			dscbd.dwFXCount    = 0;
    			dscbd.lpDSCFXDesc  = NULL;
    			hr = pIDS->CreateCaptureBuffer(&dscbd,&pDSCB,NULL);
    			if (hr == DS_OK) {
    				pDSCB->Start(DSCBSTART_LOOPING);
    				bool ping = true;
    				for (int i = 0; i < 1000; i++) {
    					DWORD cpos;
    					pDSCB->GetCurrentPosition(&cpos,NULL);
    					if (ping && (cpos >= dscbd.dwBufferBytes/2)) { // System liest im oberen Bereich ein
    						ping = false; // wir werten unten aus
    						short *pData,*pDataH;
    						DWORD size,sizeH;
    						hr = pDSCB->Lock(0,dscbd.dwBufferBytes/2,(LPVOID*)&pData,&size,(LPVOID*)&pDataH,&sizeH,0);
    						if (hr == DS_OK) {
    							EvaluateData(pData,size/2);
    							hr = pDSCB->Unlock((LPVOID)pData,size,(LPVOID)pDataH,sizeH);
    							if (hr != DS_OK) TRACE("Unlock failed: %X\n",hr);
    						} else TRACE("Lock failed: %X\n",hr);
    					} else if (!ping && (cpos < dscbd.dwBufferBytes/2)) { // System liest im unteren Bereich ein
    						ping = true; // wir werten oben aus
    						short *pData,*pDataH;
    						DWORD size,sizeH;
    						hr = pDSCB->Lock(dscbd.dwBufferBytes/2,dscbd.dwBufferBytes/2,(LPVOID*)&pData,&size,(LPVOID*)&pDataH,&sizeH,0);
    						if (hr == DS_OK) {
    							EvaluateData(pData,size/2);
    							pDSCB->Unlock((LPVOID)pData,size,(LPVOID)pDataH,sizeH);
    							if (hr != DS_OK) TRACE("Unlock failed: %X\n",hr);
    						} else TRACE("Lock failed: %X\n",hr);
    					}
    					//TRACE("cpos = %i\n",cpos);
    					Sleep(10);
    				}
    				pDSCB->Stop();
    				pIDS->Release();
    			} else TRACE("CreateCaptureBuffer failed %X\n",hr);
    		} else TRACE("GetCaps failed %X\n",hr);
    	} else TRACE("CaptureCreate failed %X\n",hr);

    Das funktioniert auf jeden Fall (wie man am Code sieht) bis 192kS/s. Wenn ich 24Bit eingebe (die das Ding eigentlich können sollte), bekomme ich einen Fehler. Aber im Grunde bin ich schon mal froh, dass ich so weit gekommen bin.

    Eine - vermutlich einfache - Frage noch:

    Die Doku zur Callback Funktion von DirectSoundCaptureEnumerate liefert mir ja Zeiger auf eine GUID und sie sagt als Bemerkung dazu:

    The memory pointed to by lpGuid, lpcstrDescription, and lpcstrModule is local in scope. If you want to save these values, you must allocate them in global memory.

    Heißt das bloß, dass ich den Zeiger auf eine meiner eigenen Strukturen - die global im System vorhanden sind - kopieren soll, oder darf ich eben genau nicht nur den Zeiger kopieren?

    Grüße

    FireHeart

    Mittwoch, 8. Juli 2015 07:17
  • Hallo Fire-Heart,
    so wie ich das verstanden habe, genügt es NICHT nur den Zeiger wegzusichern, sondern du musst eine tiefe Kopie des Speicherbereichs anfertigen.


    Viele Grüße Holger M. Rößler


    Mittwoch, 8. Juli 2015 07:21
  • Hallo Holger

    Und jetzt kommen wir meinem Problem schon immer näher:

    Wie fertigt man eine "tiefe Kopie" des Speicherbereichs an, wenn man nur diese GUID Pointer usw. hat?

    Ich fürchte, das gehört zu den Grundlagen, die ich nie gelernt hab und trotzdem irgendwie über die Runden gekommen bin....

    Grüße

    FireHeart

    Mittwoch, 15. Juli 2015 19:00
  • Hallo Fire-Heart,

    Bist Du weitergekommen? Ist der Thread noch aktuell?

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Dienstag, 28. Juli 2015 07:08
    Administrator
  • Hallo Dimitar

    Sorry, ich war die letzte Zeit anderweitig ausgelastet.

    Nein, die Frage ist für mich weiterhin aktuell: Was versteht man unter einer "tiefen Kopie", vor allem im speziellen Fall der GUID, die ich in der Callback Funktion bekomme.

    Ich habe schon versucht, die Zeiger, die ich in dieser Callback Funktion erhalte auf Zeiger der Anwendung zu kopieren...das funktioniert tatsächlich nicht.

    Ich könnte mir noch vorstellen, den Speicherbereich, auf den diese Zeiger zeigen irgendwie zu kopieren...aber wie groß sind diese Strukturen? Das wäre nicht die Vorgangsweise, die ich von Windows kenne...

    Grüße

    FireHeart

    Donnerstag, 30. Juli 2015 18:09