Allora questo è il codice che ho usato:
#include <windows.h>
#include "resource.h"
#pragma comment(lib, "Winmm.lib")
#define DIM_BUFFER_INPUT 16384
LRESULT CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);
TCHAR szNomeApp[] = TEXT("RegistratoreAudio");
OPENFILENAME ofn;
PBYTE pBuffer1, pBuffer2, pSalvaBuffer, pNuovoBuffer;
PWAVEHDR pWaveHdr1, pWaveHdr2;
HWAVEIN hWaveIn;
HWAVEOUT hWaveOut;
TCHAR szApriErrore[] = TEXT("Errore nell'apertura audio waveform!");
TCHAR szMemErrore[] = TEXT("Errore nell'allocare la memoria!");
WAVEFORMATEX waveform;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
HWND hwnd;
MSG msg = {0};
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = DialogProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = DLGWINDOWEXTRA;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szNomeApp;
RegisterClass(&wndclass); //registrazione della classe
hwnd = CreateDialog(hInstance, szNomeApp, 0, NULL);
ShowWindow(hwnd, iCmdShow); //disegna la finestra sullo schermo, con le impostazioni iniziali date dall'utente
//ciclo dei messaggi
while(GetMessage(&msg, NULL, 0, 0)) //recupera un messaggio dalla coda (restituisce FALSE (0) solo per WM_QUIT)
{
TranslateMessage(&msg); //opera alcune modifiche al messaggio a seconda della tastiera
DispatchMessage(&msg); //invia il messaggio alla window procedure appropriata
}
return msg.wParam ;
}
void MostraErrore(HWND hwnd, DWORD dwErrore)
{
TCHAR szStringErrore[1024];
//Ottiene il codice di errore mci
mciGetErrorString(dwErrore, szStringErrore, sizeof(szStringErrore) / sizeof(TCHAR));
MessageBeep(MB_ICONEXCLAMATION);
MessageBox(hwnd, szStringErrore, szNomeApp, MB_OK | MB_ICONEXCLAMATION);
}
void InitFile(HWND hwnd)
{
static TCHAR szFiltro[] = TEXT("File wave (*.wav)\0*.wav\0") \
TEXT("Tutti i files (*.*)\0*.*\0\0");
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.hInstance = NULL;
ofn.lpstrFilter = szFiltro;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = NULL; //Puntatore ad un buffer che riceve il nome del file qualificato completo (settato nelle funzioni Apri e Chiudi)
ofn.nMaxFile = MAX_PATH; //Dimensione del file
ofn.lpstrFileTitle = NULL; //Settato nelle funzioni Apri e Chiudi
ofn.nMaxFileTitle = MAX_PATH;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.lpstrFileTitle = NULL; //Settato nelle funzioni Apri e Chiudi
ofn.Flags = 0; //Setta le opzioni per la finestra di dialogo (settato nelle funzioni Apri e Chiudi)
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = TEXT("wav"); //Settato alla stringa di testo che contiene l'estenzione di default del nome del file se l'utente non ne specifica una
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
}
BOOL SaveFileDlg(HWND hwnd, PTSTR pstrNomeFile, PTSTR pstrNomeTitolo)
{
ofn.hwndOwner = hwnd;
ofn.lpstrFile = pstrNomeFile;
ofn.lpstrFileTitle = pstrNomeTitolo;
//Il flag OFN_OVERWRITEPROMPT causa una finestra di messaggio che chiede all'utente se un file
//deve essere sovrascritto se il file selezionato già esiste
ofn.Flags = OFN_OVERWRITEPROMPT;
return GetSaveFileName(&ofn); //Mostra la finestra di dialogo Salva File
}
BOOL ScriviFile(HWND hwndEdit, PTSTR pstrNomefile)
{
DWORD dwByteScritti;
HANDLE hFile;
int iLunghezza;
PTSTR pstrBuffer;
WORD wByteMark = 0xFEFF; //Byte order mark (serve per indicare che il file di testo contiene testo Unicode)
//Apre il file, lo crea se è necessario
if (INVALID_HANDLE_VALUE == (hFile = CreateFile(pstrNomefile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)))
return FALSE;
iLunghezza = GetWindowTextLength(hwndEdit); //Ottiene il numero di caratteri nell'edit control
pstrBuffer = (PTSTR)malloc((iLunghezza + 1) * sizeof(TCHAR)); //Alloca memoria per i caratteri nell'edit control
if (!pstrBuffer)
{
CloseHandle(hFile);
return FALSE;
}
//Se l'edit control restituisce il testo Unicode, scrive il byte wByteMark nel file
#ifdef UNICODE
WriteFile(hFile, &wByteMark, 2, &dwByteScritti, NULL);
#endif
GetWindowText(hwndEdit, pstrBuffer, iLunghezza + 1); //Ottiene il buffer di edit
WriteFile(hFile, &wByteMark, iLunghezza * sizeof(PBYTE), &dwByteScritti, NULL); //Scrive il buffer nel file
if ((iLunghezza * sizeof(TCHAR)) != (int)dwByteScritti)
{
CloseHandle(hFile);
free(pstrBuffer);
return FALSE;
}
CloseHandle(hFile);
free(pstrBuffer);
return TRUE;
}
LRESULT CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bRegistrare, bPlay, bInverti, bPausa, bFine, bTermina;
static DWORD dwLunghezzaDati, dwRipetizioni = 1;
static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
//static TCHAR szNomeFile[] = TEXT("record.wav");
static WORD wID_Device;
DWORD dwErrore;
//Contiene l'handle della finestra che riceve i messaggi di notifica (è usata per i messaggi di comando MCI che hanno le liste di parametri vuote; che non richiedono informazioni eccetto l'handle)
MCI_GENERIC_PARMS mciGenerico;
MCI_OPEN_PARMS mciApri; //Contiene informazioni per il comando MCI_OPEN
MCI_PLAY_PARMS mciPlay; //Contiene le informazioni di posizionamento per il comando MCI_PLAY
MCI_RECORD_PARMS mciRegistra; //Contiene le informazioni di posizionamento per il comando MCI_RECORD
MCI_SAVE_PARMS mciSalva; //Contiene le informazioni del nome del file per il comando MCI_SAVE
switch(message)
{
case WM_CREATE:
InitFile(hwnd);
return 0;
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_REGISTRA_INIZIO:
mciApri.dwCallback = 0;
mciApri.wDeviceID = 0;
mciApri.lpstrDeviceType = TEXT("waveaudio");
mciApri.lpstrElementName = TEXT("");
mciApri.lpstrAlias = NULL;
//Apre l'audio waveform
dwErrore = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD)(LPMCI_OPEN_PARMS)&mciApri);
if(dwErrore != 0)
{
MostraErrore(hwnd, dwErrore);
return TRUE;
}
//Salva il Device ID
wID_Device = mciApri.wDeviceID;
mciRegistra.dwCallback = (DWORD)hwnd;
mciRegistra.dwFrom = 0;
mciRegistra.dwTo = 0;
//Inizia la registrazione (il flag MCI_NOTIFY causa un messaggio di notifica per essere spedito alla window procedure
//quando la registrazione è stata completata)
mciSendCommand(wID_Device, MCI_RECORD, MCI_NOTIFY, (DWORD)(LPMCI_RECORD_PARMS)&mciRegistra);
EnableWindow(GetDlgItem(hwnd, IDC_REGISTRA_INIZIO), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_REGISTRA_FINE), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_INIZIA), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_FINE), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_PAUSA), FALSE);
SetFocus(GetDlgItem(hwnd, IDC_REGISTRA_FINE));
bRegistrare = TRUE;
return TRUE;
case IDC_REGISTRA_FINE:
SaveFileDlg(hwnd, szFileName, szTitleName);
ScriviFile(hwnd, szFileName);
mciGenerico.dwCallback = 0;
//Ferma la registrazione
mciSendCommand(wID_Device, MCI_STOP, MCI_WAIT, (DWORD)(LPMCI_GENERIC_PARMS)&mciGenerico);
mciSalva.dwCallback = 0;
mciSalva.lpfilename = szFileName;
//Salva il file waveform (trasferisce i dati del suono dal file temporaneo al file specificato record.wav)
mciSendCommand(wID_Device, MCI_SAVE, MCI_WAIT | MCI_SAVE_FILE, (DWORD)(LPMCI_SAVE_PARMS)&mciSalva);
//Elimina ogni file temporaneo o blocchi di memoria che possono essere stati
//creati e chiude il device waveform
mciSendCommand(wID_Device, MCI_CLOSE, MCI_WAIT, (DWORD)(LPMCI_GENERIC_PARMS)&mciGenerico);
EnableWindow(GetDlgItem(hwnd, IDC_REGISTRA_INIZIO), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_REGISTRA_FINE), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_INIZIA), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_FINE), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_PAUSA), FALSE);
SetFocus(GetDlgItem(hwnd, IDC_PLAY_INIZIA));
bRegistrare = FALSE;
return TRUE;
case IDC_PLAY_INIZIA:
waveform.wFormatTag = WAVE_FORMAT_PCM;
waveform.nChannels = 1;
waveform.nSamplesPerSec = 11025;
waveform.nAvgBytesPerSec = 11025;
waveform.nBlockAlign = 1;
waveform.wBitsPerSample = 8;
waveform.cbSize = 0;
//Apre l'audio waveform per l'output
if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveform, (DWORD)hwnd, 0, CALLBACK_WINDOW))
{
MessageBeep(MB_ICONEXCLAMATION);
MessageBox(hwnd, szApriErrore, szNomeApp, MB_ICONEXCLAMATION | MB_OK);
}
mciApri.dwCallback = 0;
mciApri.wDeviceID = 0;
mciApri.lpstrDeviceType = NULL;
mciApri.lpstrElementName = szFileName;
mciApri.lpstrAlias = NULL;
//Apre l'audio waveform (il flag MCI_OPEN_ELEMENT indica che il campo lpstrElementName è un nome di file valido);
//il primo parametro (il Device ID) non viene usato con MCI_OPEN
dwErrore = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_ELEMENT, (DWORD)(LPMCI_OPEN_PARMS)&mciApri);
if(dwErrore != 0)
{
MostraErrore(hwnd, dwErrore);
return TRUE;
}
//Salva il Device ID
wID_Device = mciApri.wDeviceID;
mciPlay.dwCallback = (DWORD)hwnd;
mciPlay.dwFrom = 0;
mciPlay.dwTo = 0;
//Inizia la riproduzione del file waveform
mciSendCommand(wID_Device, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPMCI_PLAY_PARMS)&mciPlay);
EnableWindow(GetDlgItem(hwnd, IDC_REGISTRA_INIZIO), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_REGISTRA_FINE), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_INIZIA), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_FINE), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_PAUSA), TRUE);
SetFocus(GetDlgItem(hwnd, IDC_PLAY_FINE));
bPlay = TRUE;
return TRUE;
case IDC_PLAY_PAUSA:
if(!bPausa)
{
mciGenerico.dwCallback = 0;
//Mette in pausa
mciSendCommand(wID_Device, MCI_PAUSE, MCI_WAIT, (DWORD)(LPMCI_GENERIC_PARMS)&mciGenerico);
SetDlgItemText(hwnd, IDC_PLAY_PAUSA, TEXT("Continua"));
bPausa = TRUE;
}
else
{
mciPlay.dwCallback = (DWORD)hwnd;
mciPlay.dwFrom = 0;
mciPlay.dwTo = 0;
//Ricomincia la riproduzione
mciSendCommand(wID_Device, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPMCI_PLAY_PARMS)&mciPlay);
SetDlgItemText(hwnd, IDC_PLAY_PAUSA, TEXT("Pausa"));
bPausa = FALSE;
}
return TRUE;
case IDC_PLAY_FINE:
bFine = TRUE;
//Resetta l'output per chiudere la preparazione (ferma la riproduzione e resetta la posizione corrente a 0)
waveOutReset(hWaveOut);
mciGenerico.dwCallback = 0;
//Ferma la riproduzione
mciSendCommand(wID_Device, MCI_STOP, MCI_WAIT, (DWORD)(LPMCI_GENERIC_PARMS)&mciGenerico);
//Chiude il device waveform
mciSendCommand(wID_Device, MCI_CLOSE, MCI_WAIT, (DWORD)(LPMCI_GENERIC_PARMS)&mciGenerico);
EnableWindow(GetDlgItem(hwnd, IDC_REGISTRA_INIZIO), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_REGISTRA_FINE), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_INIZIA), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_FINE), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAY_PAUSA), FALSE);
SetFocus(GetDlgItem(hwnd, IDC_PLAY_INIZIA));
bPlay = FALSE;
bPausa = FALSE;
return TRUE;
}
case MM_MCINOTIFY:
switch(wParam)
{
case MCI_NOTIFY_SUCCESSFUL:
if(bPlay)
SendMessage(hwnd, WM_COMMAND, IDC_PLAY_FINE, 0);
if(bRegistrare)
SendMessage(hwnd, WM_COMMAND, IDC_REGISTRA_FINE, 0);
return TRUE;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
Ti sarei veramente grato se mi aiutassi a risolvere il problema.
Ti ringrazio in anticipo.