Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Consulta para crear un vumetro/ecualizador (https://www.clubdelphi.com/foros/showthread.php?t=89522)

c64 06-12-2015 06:30:22

Consulta para crear un vumetro/ecualizador
 
1 Archivos Adjunto(s)
Estube buscando informacion para crear un vumetro o algunos le llaman ecualizador. En definitiva el de la imagen que posteo.



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.

Código:

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.

Código:

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).

Código:

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
Cita:

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.
Cita:

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).

Código:

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.

Código:

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.

c64 06-12-2015 06:35:04

1 Archivos Adjunto(s)
Adjunto un ejemplo que encontre (ruso) realizado en DirectX, aunque uso librerias externas aparentemente, es decir que no vienen instaladas en builder.

ecfisa 06-12-2015 12:22:16

Hola c64.

Creo que vas a encontrar información interesante en los enlaces citados en este antiguo hilo del foro: Ecualizador

Saludos :)

c64 07-12-2015 00:44:42

Cita:

Empezado por ecfisa (Mensaje 500251)
Hola c64.

Creo que vas a encontrar información interesante en los enlaces citados en este antiguo hilo del foro: Ecualizador

Saludos :)

Gracias ecfisa la pagina que me pasaste es relacionada a tratamiento de audio y plugins sobre programas segun vi, pero es bastante mas avanzado, no busco ecualizar la señal solo hacer el vumetro (buscar en los datos donde estan los golpes, que seria en el buffer cuando hay mas informacion (con eso ya me conformo). Buscando en internet encontre esto como para que vaya enriqueciendo el post.

Tratamiento a bajo nivel con DirectX y demas
http://wainu.ii.uned.es/ing_informat..._audio_cpp.pdf

Tratamiento con la API de windows (como el ejemplo que subi)
http://www.dreamincode.net/forums/to...dows-api-in-c/

Estoy agarrandole la mano al Builder, pero las API y Direct X son otra cosa totalmente distinta para mi.

Por cierto si alguno probo el codigo que subi arriba, y lo ejecuto, el archivo que genera es uno llamado a (sin extension ni nada), si lo renombran a a.wav ahi tendran el sonido en wav, no pude ponerle la extension ya que me tomaba el alfabeto asiatico nose porque.


La franja horaria es GMT +2. Ahora son las 01:24:00.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi