Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1

    [C++ Win32] diversi modi di allocare buffers (WAVEHDR)

    Salve,

    volevo chiedere un parere su quale secondo voi potesse essere la migliore via per preparare diversi buffer (WAVEHDR) da usare per la cattura audio tramite le waveForm API.

    Il seguente codice mi è stato consigliato proprio su questo forum e devo dire che funziona alla perfezione, forse magari fa troppo uso dell'operatore new, ma per il resto credo vada bene:

    codice:
    WAVEHDR **buff = new WAVEHDR*[num_buffers];
    
    for (int i = 0; i<num_buffers; i++)
    {
    	buff[i] = new WAVEHDR;
    	ZeroMemory(buff[i],sizeof(WAVEHDR));
    
    	buff[i]->lpData          = (char*) malloc(system_buf_len);
    	buff[i]->dwBufferLength  = system_buf_len;
    	buff[i]->dwBytesRecorded = 0;
    	buff[i]->dwUser          = 0;
    	buff[i]->dwFlags         = 0;
    	buff[i]->dwLoops         = 0;
    
    	waveInPrepareHeader(hwi, buff[i], sizeof(WAVEHDR));
    	waveInAddBuffer(hwi, buff[i], sizeof(WAVEHDR));
    }
    Tuttavia anche il codice di seguito potrebbe andare bene, inoltre non c'è nessuna allocazione dinamica:

    codice:
    #include <vector>
    
    typedef std::vector<WAVEHDR> WaveHdrArray;
    typedef std::vector<char> CharArray;
    
    (...)
    
    WaveHdrArray buff(num_buffers);
    CharArray chArray(system_buf_len * num_buffers);
    
    for (int i = 0; i<num_buffers; i++)
    {
    	ZeroMemory(&buff[i],sizeof(WAVEHDR));
    
    	buff[i].lpData = &chArray[i * system_buf_len];
    	buff[i].dwBufferLength  = system_buf_len;
    	buff[i].dwBytesRecorded = 0;
    	buff[i].dwUser          = 0;
    	buff[i].dwFlags         = 0;
    	buff[i].dwLoops         = 0;
    
    	waveInPrepareHeader(hwi, &buff[i], sizeof(WAVEHDR));
    	waveInAddBuffer(hwi, &buff[i], sizeof(WAVEHDR));
    }
    cosa ne pensate?

    grazie
    Alla batteria dai retta ballA

  2. #2
    ecco un codice completo che mostra l'uso di vector per evitare allocazioni...ho messo il tutto in un file solo così potete provarlo senza problemi:

    codice:
    /*
     *
     * main.cpp (v0.2) (Author: THEARTOFWEB Software - theartofweb@hotmail.com)
     *
     * Capture and record audio from an input device by using the Win32 waveForm API
     *
     */
    
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #pragma comment (lib, "winmm.lib")
    #include <mmsystem.h>
    #include <process.h>
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <stdlib.h>
    using namespace std;
    
    unsigned __stdcall startRecorder (void* lpParam);
    unsigned __stdcall stopRecorder (void*);
    
    bool createWAVEFile(const char*);
    bool saveWAVEChunk(const char*, const DWORD);
    bool closeWAVEFile(void);
    
    DWORD dwBufferLength         = 176400;
    DWORD dwNumBuffers           = 3;
    DWORD uDevice                = 0; // Built-in Microphone
    
    const char* szFilePath       = "C:\\Users\\giangaetano\\Desktop\\mmio\\waveCapture.WAVE";
    bool volatile stopThreadFlag = false;
    DWORD dwTotalBytesRecorded   = 0;
    
    std::ofstream hFile;
    WAVEFORMATEX wf;
    
    enum WAVECAPTURE_ERROR {
    	ERR_WAVEINOPEN          = -1,
    	ERR_WAVEINSTART         = -2,
    	ERR_WAVEINPREPAREHEADER = -3,
    	ERR_WAVEINADDBUFFER     = -4,
    	ERR_NOERROR             = 0,
    	ERR_ALREADYSTARTED      = -5,
    	ERR_BUFFERALLOC         = -6,
    	ERR_EVENTNULL           = -10,
    	ERR_OPENFILE            = -20,
    	ERR_SAVECHUNK           = -21,
    	ERR_CLOSEFILE           = -22
    };
    
    int main()
    {
    	HANDLE hThread[2];
    	unsigned ThreadId[2];
    
    	// Start capturing Thread: thread[0]
    	hThread[0] = (HANDLE)_beginthreadex(NULL, 0, startRecorder, NULL, 0, &ThreadId[0]);
    	if (hThread[0] == 0)
    	{
    		cout << "thread[0] error" << endl;
    		return -1;
    	}
    
    	cout << "Started capturing...(press any key to stop)" << endl;
    	system("pause");
    
    	// Stop thread[0] by lanching thread[1]
    	hThread[1] = (HANDLE)_beginthreadex(NULL, 0, stopRecorder, NULL, 0, &ThreadId[1]);
    	if (hThread[1] == 0)
    	{
    		cout << "thread[1] error" << endl;
    		return -1;
    	}
    
    	WaitForMultipleObjects(2, hThread, true, INFINITE);
    
    	CloseHandle(hThread[0]);
    	CloseHandle(hThread[1]);
    
    	cout << "Stopped capturing!" << endl;
    	cout << "Total Bytes Recorded: " << dwTotalBytesRecorded << endl;
    
    	system("pause");
    	return EXIT_SUCCESS;
    }
    
    unsigned __stdcall startRecorder (void* lpParam)
    {
    	// Define WAVEFORMATEX
    	wf.wFormatTag      = WAVE_FORMAT_PCM;
    	wf.wBitsPerSample  = 16;
    	wf.nChannels       = 2;
    	wf.nSamplesPerSec  = 44100;
    	wf.nBlockAlign     = (wf.nChannels * wf.wBitsPerSample) / 8;
    	wf.nAvgBytesPerSec = (wf.nSamplesPerSec * wf.nBlockAlign);
    	wf.cbSize          = 0;
    
    	// Create event
    	HANDLE hevent = CreateEvent(NULL,FALSE,FALSE,NULL);
    	if(hevent == NULL)
    		return ERR_EVENTNULL;
    
    	// WaveInOpen
    	HWAVEIN hwi;
    	if(waveInOpen(&hwi,uDevice,(LPWAVEFORMATEX)&wf,(DWORD)hevent,0,CALLBACK_EVENT)
    		!= MMSYSERR_NOERROR)
    		return ERR_WAVEINOPEN;
    
    	// Define WAVEHDR Structure
    	std::vector<WAVEHDR> buff(dwNumBuffers);
    	std::vector<char> pool(dwNumBuffers * dwBufferLength);
    
    	for (int i = 0; i<(int)dwNumBuffers; i++)
    	{
    		ZeroMemory(&buff[i],sizeof(WAVEHDR));
    		buff[i].lpData          = &pool[i * dwBufferLength];
    		buff[i].dwBufferLength  = dwBufferLength;
    		buff[i].dwBytesRecorded = 0;
    		buff[i].dwUser          = 0;
    		buff[i].dwFlags         = 0;
    		buff[i].dwLoops         = 0;
    
    		if(waveInPrepareHeader(hwi, &buff[i], sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
    			return ERR_WAVEINPREPAREHEADER;
    
    		if(waveInAddBuffer(hwi, &buff[i], sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
    			return ERR_WAVEINADDBUFFER;
    	}
    
    	// Start capturing...
    	if(waveInStart(hwi) != MMSYSERR_NOERROR)
    		return ERR_WAVEINSTART;
    
    	// Alloc "local" buffer
    	std::vector<char> pWAVBuffer(dwBufferLength);
    
    	// Create WAVE file
    	if(!createWAVEFile(szFilePath))
    		return ERR_OPENFILE;
    
    	// Loop: capturing...
    	int k = 0;
    	while(1)
    	{
    		if(stopThreadFlag)
    			break;
    
    		// CALLBACK EVENT
    		WaitForSingleObject(hevent, INFINITE);
    
    		if(buff[k].dwFlags & WHDR_DONE)
    		{
    			memcpy(&pWAVBuffer[0], buff[k].lpData, buff[k].dwBytesRecorded);
    
    			cout << buff[k].dwBytesRecorded << endl;
    			dwTotalBytesRecorded += buff[k].dwBytesRecorded;
    
    			if(!saveWAVEChunk(&pWAVBuffer[0], buff[k].dwBytesRecorded))
    				return ERR_SAVECHUNK;
    
    			if(waveInAddBuffer(hwi, &buff[k], sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
    				return ERR_WAVEINADDBUFFER;
    		}
    
    		if(k == dwNumBuffers-1)
    			k=0;
    		else
    			k++;
    	}
    
    	// Close WAVE file
    	if(!closeWAVEFile())
    		return ERR_CLOSEFILE;
    
    	// Unprepare header
    	MMRESULT h;  
    	for (int u = 0; u<(int)dwNumBuffers; u++)
    	{
    		do {
    			h = waveInUnprepareHeader(hwi, &buff[u], sizeof(WAVEHDR));
    		} while (h != MMSYSERR_NOERROR); 
    	}
    
    	waveInClose(hwi);
    	CloseHandle(hevent);
    
    	return ERR_NOERROR;
    }
    
    unsigned __stdcall stopRecorder (void*)
    {
    	stopThreadFlag = true;
    	return 0;
    }
    
    bool createWAVEFile(const char*)
    {
    	char nullbuff[44];
    	ZeroMemory(&nullbuff, sizeof(nullbuff));
    
    	hFile.open( szFilePath, std::ios::out|std::ios::binary );
    	if(hFile.bad())
    		return false;
    
    	hFile.write(nullbuff, 44);
    
    	return true;
    }
    
    bool saveWAVEChunk(const char* pWAVBuffer, const DWORD bufflen)
    {
    	hFile.write(pWAVBuffer, bufflen);
    	if(hFile.bad())
    		return false;
    
    	return true;
    }
    
    bool closeWAVEFile(void)
    {
    	// close file and re-open it to add the header at the beginning:
    	hFile.close();
    
    	MMCKINFO mmckinfo;
    	MMCKINFO mmckinfoSubchunk;
    	MMCKINFO mmckinfoData;
    
    	memset(&mmckinfo, 0, sizeof(mmckinfo));
    	memset(&mmckinfoSubchunk, 0, sizeof(mmckinfoSubchunk));
    	memset(&mmckinfoData, 0, sizeof(mmckinfoData));
    
    	// Open the WAVE file using mmio (no create!)
    	// creating a file using mmio
    	HMMIO hfile;
    	hfile = mmioOpen((LPSTR)szFilePath, NULL, MMIO_WRITE);
    	mmioSeek(hfile, 0, SEEK_SET);
    	//step 1 create riff chunk
    	mmckinfo.fccType = mmioFOURCC('W','A','V','E');
    	mmckinfo.cksize = (36 + dwTotalBytesRecorded);
    	mmioCreateChunk(hfile, &mmckinfo, MMIO_CREATERIFF);
    	
    	//step 2 create fmt chunk
    	//creating fmt chunk also includes writing formatex to this chunk
    	mmckinfoSubchunk.ckid   = mmioFOURCC('f','m','t',' ');
    	mmckinfoSubchunk.cksize = sizeof(WAVEFORMATEX);
    
    	mmioCreateChunk(hfile, &mmckinfoSubchunk, 0);
    	mmioWrite(hfile, (char*)&wf, sizeof(wf));
    	mmioAscend(hfile, &mmckinfoSubchunk, 0);
    
    	//step 3 creating data chunk
    	//creating this chunk includes writing actual voice data
    	mmckinfoData.ckid=mmioFOURCC('d','a','t','a');
    	mmckinfoData.cksize = dwTotalBytesRecorded;
    	mmioCreateChunk(hfile, &mmckinfoData, 0);
    
    	mmioClose( MMIO_READ, MMIO_FHOPEN );
    
    	return true;
    }
    grazie
    Alla batteria dai retta ballA

  3. #3
    Visual Studio mi da questo errore:

    Errore 1 error C2664: 'mmioOpenW': impossibile convertire il parametro 1 da 'LPSTR' a 'LPWSTR' c:\users\pindol\documents\visual studio 2008\projects\recordaudio\main.cpp 228 recordAudio

    Come mai?


    Risolto, c'è un errore di scrittura nel cast va messo LPWSTR

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Il codice è corretto. Devi solo settare il compilatore per non usare UNICODE ( che fa di default ).
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  5. #5
    ok chiedo scusa per la mia ignoranza!

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Niente paura. Ogni tanto capita che sfugga quel piccolo dettaglio.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  7. #7
    altra domanda idiota, una volta registrato, salva il file in formato wave. Con che programma lo apro questo file?

    Grazie per l'aiuto che mi hai dato fino ad ora

  8. #8
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Provato con Windows Media Player, Vlc o simili?
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  9. #9
    Quicktime, iTunes...
    Alla batteria dai retta ballA

  10. #10
    Con windows media player e vlc non va, ora provo quick time

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.