c64
06-12-2015, 05:30:22
Estube buscando informacion para crear un vumetro o algunos le llaman ecualizador. En definitiva el de la imagen que posteo.
http://www.digitaldjtips.com/wp-content/uploads/2011/09/vu-meters1.jpg
No entiendo mucho o muy poco, sobre el MCI o el DirectX, asi que me puse a buscar e intentar entender algo. Y esto es lo que mas o menos encontre (tenganme paciencia).
Encontre este tutorial soobre el MCI de windows. edn.embarcadero.com/article/28332#sthash.AuLj1Nc0.dpuf y encontre un lugar chino donde habian posteado parte del codigo, trastee para que ande y es lo que adjunto como zip abajo (esta funcionando).
En resumen Abre el MCI y lo configura si esto WS_VISIBLE esta comentado no lo muestra en pantalla.
m_hMCIWnd=MCIWndCreate(Handle,
g_hInstance,
// WS_VISIBLE |
WS_CHILD | WS_OVERLAPPED | WS_CAPTION | WS_BORDER |
MCIWNDF_RECORD | MCIWNDF_SHOWALL,
NULL );
Luego setea la configuracion a grabar (me olvide de cambiar los parametros antes de subirlo.
MCI_WAVE_SET_PARMS set_parms;
set_parms.wFormatTag = WAVE_FORMAT_PCM;
set_parms.wBitsPerSample = 16; // aca deberia ir 8
set_parms.nChannels = 1;
set_parms.nBlockAlign = (set_parms.nChannels*set_parms.wBitsPerSample)/8;
set_parms.nSamplesPerSec = 44100; // y aqui 11025
Deberian cambiarse porque en definitiva no nos interesa la calidad sino buscar los golpes en el audio, es decir cuando el buffer empieza a llenarse de informacion. Si en ese segundo sube de tamaño es que hay un golpe o sonido que puede mover el sonido.
Luego el codigo graba la informacion (y aqui nose como ni de donde toma los datos).
char file[260]="";
wsprintf(file,"a",GetTickCount()%100000L); // random filename
//
// now stop audio and save to disk
MCIWndStop(m_hMCIWnd);
MCIWndSave(m_hMCIWnd,file);
MCIWndClose(m_hMCIWnd);
En este momento estoy leyendo dos cosas esto para ver como funciona el MCI
msdn.microsoft.com/en-us/library/aa446573/
clubdelphi.com/foros/showthread.php?t=2020
Ok.. El tema es que no es solo una API, hay que abrir el canal , por ejemplo con waveInOpen si vamos a usar WaveIns, debes gestionar la memoria para los buffers de entrada (WaveInPrepareHeader y waveInAddBuffer) y con waveInStart empiezas a recibir datos en una CallBack.... Cuando finalices la operación hay que cerrar todo.
Este procedimiento CallBack recibe un los buffers, cuanto mas pequeños los crees, más se asemejara a "Tiempo Real", pero producirá que recaiga la performace de tu sistema. Si recorres este buffer puede encontrarte con los valores de sonido como para realizar un vúmetro.
Ahora... el código que utilizas para realizar la grabación debe utilizar winmm con la API waveInAddBuffer para obtener la onda en un vector; en tal caso y dependiendo del formato definido en waveInOpen podrás conocer el “valor de silencio”; por ejemplo... cuando utilizas PCM, mono y 1 byte por muestra; los valores de la onda son igual a Abs(v[i]-$80); en tal caso el silencio esta dado por un 128 +/- ruido.
El anterior caso varía dependiendo de los canales de grabacion, y los bytes por muestra.
y un ejemplo que postearon en este foro pero echo en delphi (lamentablemente no encuentro el link, lo subio como onda.zip).
if waveInOpen(@Device,WAVE_MAPPER,@wfx,Handle,0,CALLBACK_WINDOW) = MMSYSERR_NOERROR then
begin
BufferSize:= wfx.nBlockAlign * (wfx.nSamplesPerSec div BuffersPerSec);
Width:= BufferSize;
for i:= 1 to BuffersPerSec do
begin
GetMem(WaveBuffers[i],BufferSize);
with WaveHeaders[i] do
begin
lpData:= WaveBuffers[i];
dwBufferLength:= BufferSize;
dwBytesRecorded := 0;
dwUser := i;
dwFlags := 0;
dwLoops := 0;
lpNext := nil;
reserved := 0;
end;
end;
isDeviceOpen:= TRUE;
for i:= 1 to BuffersPerSec do
if waveInPrepareHeader(Device,@WaveHeaders[i],sizeof(TWAVEHDR))<>MMSYSERR_NOERROR then
begin
CloseWaveDevice;
exit;
end;
for i:= 1 to BuffersPerSec do
if waveInAddBuffer(Device,@WaveHeaders[i],sizeof(TWAVEHDR))<>MMSYSERR_NOERROR then
begin
CloseWaveDevice;
exit;
end;
waveInStart(Device);
end;
end;
La parte del grafico en si.
hdr:= PWaveHdr(Msg.LParam);
with hdr^ do
begin
P:= PByte(lpData);
Canvas.FillRect(Canvas.ClipRect);
Canvas.MoveTo(width,128);
Canvas.LineTo(0,128);
for i:= 1 to dwBytesRecorded do
begin
Canvas.LineTo(i,P^);
inc(P);
end;
end;
Creo que voy bien encaminado ahora estoy investigando como funciona el waveInOpen. Diganme que les parece el tema.
Otra manera de obtener audio es mediante directX, pero ahi estoy mas perdido aun.
http://www.digitaldjtips.com/wp-content/uploads/2011/09/vu-meters1.jpg
No entiendo mucho o muy poco, sobre el MCI o el DirectX, asi que me puse a buscar e intentar entender algo. Y esto es lo que mas o menos encontre (tenganme paciencia).
Encontre este tutorial soobre el MCI de windows. edn.embarcadero.com/article/28332#sthash.AuLj1Nc0.dpuf y encontre un lugar chino donde habian posteado parte del codigo, trastee para que ande y es lo que adjunto como zip abajo (esta funcionando).
En resumen Abre el MCI y lo configura si esto WS_VISIBLE esta comentado no lo muestra en pantalla.
m_hMCIWnd=MCIWndCreate(Handle,
g_hInstance,
// WS_VISIBLE |
WS_CHILD | WS_OVERLAPPED | WS_CAPTION | WS_BORDER |
MCIWNDF_RECORD | MCIWNDF_SHOWALL,
NULL );
Luego setea la configuracion a grabar (me olvide de cambiar los parametros antes de subirlo.
MCI_WAVE_SET_PARMS set_parms;
set_parms.wFormatTag = WAVE_FORMAT_PCM;
set_parms.wBitsPerSample = 16; // aca deberia ir 8
set_parms.nChannels = 1;
set_parms.nBlockAlign = (set_parms.nChannels*set_parms.wBitsPerSample)/8;
set_parms.nSamplesPerSec = 44100; // y aqui 11025
Deberian cambiarse porque en definitiva no nos interesa la calidad sino buscar los golpes en el audio, es decir cuando el buffer empieza a llenarse de informacion. Si en ese segundo sube de tamaño es que hay un golpe o sonido que puede mover el sonido.
Luego el codigo graba la informacion (y aqui nose como ni de donde toma los datos).
char file[260]="";
wsprintf(file,"a",GetTickCount()%100000L); // random filename
//
// now stop audio and save to disk
MCIWndStop(m_hMCIWnd);
MCIWndSave(m_hMCIWnd,file);
MCIWndClose(m_hMCIWnd);
En este momento estoy leyendo dos cosas esto para ver como funciona el MCI
msdn.microsoft.com/en-us/library/aa446573/
clubdelphi.com/foros/showthread.php?t=2020
Ok.. El tema es que no es solo una API, hay que abrir el canal , por ejemplo con waveInOpen si vamos a usar WaveIns, debes gestionar la memoria para los buffers de entrada (WaveInPrepareHeader y waveInAddBuffer) y con waveInStart empiezas a recibir datos en una CallBack.... Cuando finalices la operación hay que cerrar todo.
Este procedimiento CallBack recibe un los buffers, cuanto mas pequeños los crees, más se asemejara a "Tiempo Real", pero producirá que recaiga la performace de tu sistema. Si recorres este buffer puede encontrarte con los valores de sonido como para realizar un vúmetro.
Ahora... el código que utilizas para realizar la grabación debe utilizar winmm con la API waveInAddBuffer para obtener la onda en un vector; en tal caso y dependiendo del formato definido en waveInOpen podrás conocer el “valor de silencio”; por ejemplo... cuando utilizas PCM, mono y 1 byte por muestra; los valores de la onda son igual a Abs(v[i]-$80); en tal caso el silencio esta dado por un 128 +/- ruido.
El anterior caso varía dependiendo de los canales de grabacion, y los bytes por muestra.
y un ejemplo que postearon en este foro pero echo en delphi (lamentablemente no encuentro el link, lo subio como onda.zip).
if waveInOpen(@Device,WAVE_MAPPER,@wfx,Handle,0,CALLBACK_WINDOW) = MMSYSERR_NOERROR then
begin
BufferSize:= wfx.nBlockAlign * (wfx.nSamplesPerSec div BuffersPerSec);
Width:= BufferSize;
for i:= 1 to BuffersPerSec do
begin
GetMem(WaveBuffers[i],BufferSize);
with WaveHeaders[i] do
begin
lpData:= WaveBuffers[i];
dwBufferLength:= BufferSize;
dwBytesRecorded := 0;
dwUser := i;
dwFlags := 0;
dwLoops := 0;
lpNext := nil;
reserved := 0;
end;
end;
isDeviceOpen:= TRUE;
for i:= 1 to BuffersPerSec do
if waveInPrepareHeader(Device,@WaveHeaders[i],sizeof(TWAVEHDR))<>MMSYSERR_NOERROR then
begin
CloseWaveDevice;
exit;
end;
for i:= 1 to BuffersPerSec do
if waveInAddBuffer(Device,@WaveHeaders[i],sizeof(TWAVEHDR))<>MMSYSERR_NOERROR then
begin
CloseWaveDevice;
exit;
end;
waveInStart(Device);
end;
end;
La parte del grafico en si.
hdr:= PWaveHdr(Msg.LParam);
with hdr^ do
begin
P:= PByte(lpData);
Canvas.FillRect(Canvas.ClipRect);
Canvas.MoveTo(width,128);
Canvas.LineTo(0,128);
for i:= 1 to dwBytesRecorded do
begin
Canvas.LineTo(i,P^);
inc(P);
end;
end;
Creo que voy bien encaminado ahora estoy investigando como funciona el waveInOpen. Diganme que les parece el tema.
Otra manera de obtener audio es mediante directX, pero ahi estoy mas perdido aun.