Mezclar dos señales de audio.

Dudas, cuestiones, sugerencias y peticiones en general sobre el proyecto / Questions and requests about the project
Responder
Avatar de Usuario
neuro_999
Mensajes: 692
Registrado: 06 Oct 2015, 10:14

Mezclar dos señales de audio.

Mensaje por neuro_999 » 23 Ago 2017, 16:39

Preparando los cores arcades para el futuro addon jamma de antonio, necesitaba mezclar los dos canales de sonido del galaxian., ya que utiliza un dac para los sonkdos generados y otro para los samples, y los saca independientes cada uno por un canal del stereo del zxuno... El caso es que jamma solo tiene mono y x ma vueltas que le doy no lo consigo.
Lo he intentado con un and en las dos salidas del los dacs... Y me mezcla mucho ruido en la salida, y tambien lo he intentado mezclando los datos que van a la entrada del dac (dos señales de 8 bits) antes de meterlos al dac, pero nada... Consigo reducir los ruidos, pero no doy con la formula correcta.
Alguien me podria echar una mano y decirme ¿como mezclar las dos señales de sonido?. Me valdría si es antes o después de pasar x el dac, eso me da igual.... La señal como he dicho es un vector de 8 bits (antes de que pase x el dac y la convierta a señal de salida).
Muchas gracias, a ver si alguien me ayuda, no pensaba que esto de mezclar sonido era tan difícil, después de haber visto a kiko rivera [emoji2]

Añado los datos del fuente relevantes:
signal W_DAC_A : std_logic := '0';
signal W_DAC_B : std_logic := '0';
signal W_SDAT_A : std_logic_vector( 7 downto 0) := (others => '0');
signal W_SDAT_B : std_logic_vector( 7 downto 0) := (others => '0');

mc_sound_a : entity work.MC_SOUND_A
port map(
I_CLK_12M => W_CLK_12M,
I_CLK_6M => W_CLK_6M,
I_H_CNT1 => W_H_CNT(1),
I_BD => W_BDI,
I_PITCHn => W_PITCHn,
I_VOL1 => W_VOL1,
I_VOL2 => W_VOL2,
O_SDAT => W_SDAT_A,
O_DO => open
);

mc_sound_b : entity work.MC_SOUND_B
port map(
I_CLK1 => W_CLK_6M,
I_RSTn => rst_count(3),
I_SW => new_sw,
I_DAC => W_DAC,
I_FS => W_FS,
O_SDAT => W_SDAT_B
);

wav_dac_a : entity work.dac
port map(
clk_i => W_CLK_18M,
res_n_i => W_RESETn,
dac_i => W_SDAT_A,
dac_o => W_DAC_A
);

wav_dac_b : entity work.dac
port map(
clk_i => W_CLK_18M,
res_n_i => W_RESETn,
dac_i => W_SDAT_B,
dac_o => W_DAC_B
);

(dac.vhd)
-------------------------------------------------------------------------------
--
-- Delta-Sigma DAC
--
-- $Id: dac.vhd,v 1.1 2006/05/10 20:57:06 arnim Exp $
--
-- Refer to Xilinx Application Note XAPP154.
--
-- This DAC requires an external RC low-pass filter:
--
-- dac_o 0---XXXXX---+---0 analog audio
-- 3k3 |
-- === 4n7
-- |
-- GND
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity DAC is

generic (
msbi_g : integer := 7
);
port (
clk_i : in std_logic;
res_n_i : in std_logic;
dac_i : in std_logic_vector(msbi_g downto 0);
dac_o : out std_logic
);

end;

architecture RTL of dac is
signal sig_in : unsigned(msbi_g+2 downto 0) := (others => '0');

begin
seq: process (clk_i, res_n_i)
begin
if res_n_i = '0' then
sig_in <= to_unsigned(2**(msbi_g+1), sig_in'length);
dac_o <= '0';
elsif rising_edge(clk_i) then
sig_in <= sig_in + unsigned(sig_in(msbi_g+2) & sig_in(msbi_g+2) & dac_i);
dac_o <= sig_in(msbi_g+2);
end if;
end process seq;
end RTL;


Enviado desde mi ONE A2003 mediante Tapatalk

Avatar de Usuario
Kyp
Mensajes: 240
Registrado: 18 May 2016, 20:16

Re: Mezclar dos señales de audio.

Mensaje por Kyp » 23 Ago 2017, 17:05

Puedes hacerlo de dos formas:
- Sumando los dos vectores en un tercero un bit más grande para no perder precisión y pasando la suma al DAC.
- Multiplexando las señales. Un contador de 1 bit que cambie con el clock y cuando es cero le pasas al DAC una señal y cuando es 1 la otra.

Tanto el ZX-Uno como mi core usan el método de multiplexar señales.

Avatar de Usuario
neuro_999
Mensajes: 692
Registrado: 06 Oct 2015, 10:14

Re: Mezclar dos señales de audio.

Mensaje por neuro_999 » 23 Ago 2017, 17:51

Lo del multiplexado lo probe con la señal de la salida y no me funciono, pero claro, no se me ocurrio hacerlo en la de entrada. Voy a probarlo y mañana te cuento. Muchas gracias.

Enviado desde mi ONE A2003 mediante Tapatalk

Avatar de Usuario
Kyp
Mensajes: 240
Registrado: 18 May 2016, 20:16

Re: Mezclar dos señales de audio.

Mensaje por Kyp » 23 Ago 2017, 18:15

El DAC tiene que ser el último paso. Los datos le tienen que llegar ya 'apañaos' :)

Avatar de Usuario
mcleod_ideafix
Mensajes: 831
Registrado: 27 Sep 2015, 00:14
Ubicación: Jerez de la Frontera
Contactar:

Re: Mezclar dos señales de audio.

Mensaje por mcleod_ideafix » 24 Ago 2017, 03:42

Suponiendo que las señales de entrada (las que van originalmente a cada DAC por separado) son de 8 bits sin signo, una forma de mezclarlas es usando este módulo:

Código: Seleccionar todo

module mixer (
  input wire [7:0] audio1,
  input wire [7:0] audio2,
  output wire [7:0] mezcla
  );  

  wire [8:0] suma;
  assign suma = audio1 + audio2;
  assign mezcla = {~suma[8], suma[7:1]};
endmodule
O sea: sumas las dos señales de audio original, y del resultado, de 9 bits, coges los 8 bits más significativos, pero cuidando de invertir el bit más significativo de esos 8 (lo cual es equivalente a sumar 256 a suma).

El método de multiplexar en el tiempo las dos señales de audio quedaría una cosa así:

Código: Seleccionar todo

module mixer (
  input wire clk,  // el mismo reloj que se use en el DAC
  input wire [7:0] audio1,
  input wire [7:0] audio2,
  output reg [7:0] mezcla
  );
  
  reg [8:0] cnt = 9'd0;
  always @(posedge clk) begin
    cnt <= cnt + 9'd1;
    if (cnt[8] == 1'b0)
      mezcla <= audio1;
    else
      mezcla <= audio2;
  end
endmodule
Aquí se van enviando alternativamente muestras de audio1 y audio2, pero no en cada ciclo de reloj, sino cada 256 ciclos de reloj, para que al DAC le dé tiempo de construir un sample analógico, que le lleva precisamente 256 ciclos de reloj. Este método asume que las señales audio1 y audio2 cambian con mucha menor velocidad que el reloj clk. De hecho, clk debería tener una frecuencia igual o superior a 256 (2^8, o sea, 2 elevado a 8) veces la frecuencia de muestreo que se pretende conseguir en el conversor digital-analógico.

Así, si se sabe que las señales de audio no van a una frecuencia mayor de 10kHz, se muestrean en 8 bits, y hay 2 señales para multiplexar, la frecuencia mínima que se necesita en el DAC (y en este módulo) es de 10000 * 2^8 * 2 = 5.12 MHz.
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA

Avatar de Usuario
neuro_999
Mensajes: 692
Registrado: 06 Oct 2015, 10:14

Re: RE: Re: Mezclar dos señales de audio.

Mensaje por neuro_999 » 24 Ago 2017, 09:05

mcleod_ideafix escribió:Suponiendo que las señales de entrada (las que van originalmente a cada DAC por separado) son de 8 bits sin signo, una forma de mezclarlas es usando este módulo:

Código: Seleccionar todo

module mixer (
  input wire &#91;7&#58;0&#93; audio1,
  input wire &#91;7&#58;0&#93; audio2,
  output wire &#91;7&#58;0&#93; mezcla
  );  

  wire &#91;8&#58;0&#93; suma;
  assign suma = audio1 + audio2;
  assign mezcla = {~suma&#91;8&#93;, suma&#91;7&#58;1&#93;};
endmodule
O sea: sumas las dos señales de audio original, y del resultado, de 9 bits, coges los 8 bits más significativos, pero cuidando de invertir el bit más significativo de esos 8 (lo cual es equivalente a sumar 256 a suma).

El método de multiplexar en el tiempo las dos señales de audio quedaría una cosa así:

Código: Seleccionar todo

module mixer (
  input wire clk,  // el mismo reloj que se use en el DAC
  input wire &#91;7&#58;0&#93; audio1,
  input wire &#91;7&#58;0&#93; audio2,
  output reg &#91;7&#58;0&#93; mezcla
  );
  
  reg &#91;8&#58;0&#93; cnt = 9'd0;
  always @(posedge clk) begin
    cnt <= cnt + 9'd1;
    if (cnt&#91;8&#93; == 1'b0)
      mezcla <= audio1;
    else
      mezcla <= audio2;
  end
endmodule
Aquí se van enviando alternativamente muestras de audio1 y audio2, pero no en cada ciclo de reloj, sino cada 256 ciclos de reloj, para que al DAC le dé tiempo de construir un sample analógico, que le lleva precisamente 256 ciclos de reloj. Este método asume que las señales audio1 y audio2 cambian con mucha menor velocidad que el reloj clk. De hecho, clk debería tener una frecuencia igual o superior a 256 (2^8, o sea, 2 elevado a 8) veces la frecuencia de muestreo que se pretende conseguir en el conversor digital-analógico.

Así, si se sabe que las señales de audio no van a una frecuencia mayor de 10kHz, se muestrean en 8 bits, y hay 2 señales para multiplexar, la frecuencia mínima que se necesita en el DAC (y en este módulo) es de 10000 * 2^8 * 2 = 5.12 MHz.
Perfecto, funciona genial.
Lo he puesto en el modullo top de verilog para multiplexar a la salida (asi no tg que modificar todos los arcades que usan la placa del galaxian) y va de coña.
Muchisimas gracias, sois la releche. [img]https://uploads.tapatalk-cdn.com/201708 ... 6b03e3.jpg[/img]

Enviado desde mi ONE A2003 mediante Tapatalk

Avatar de Usuario
Kyp
Mensajes: 240
Registrado: 18 May 2016, 20:16

Re: Mezclar dos señales de audio.

Mensaje por Kyp » 24 Ago 2017, 09:39

mcleod_ideafix escribió: Aquí se van enviando alternativamente muestras de audio1 y audio2, pero no en cada ciclo de reloj, sino cada 256 ciclos de reloj, para que al DAC le dé tiempo de construir un sample analógico, que le lleva precisamente 256 ciclos de reloj.
Interesante apreciación. A ver si esto resuelve un problema que me he encontrado implementando el SpecDrum en mi core.
mcleod_ideafix escribió: Este método asume que las señales audio1 y audio2 cambian con mucha menor velocidad que el reloj clk. De hecho, clk debería tener una frecuencia igual o superior a 256 (2^8, o sea, 2 elevado a 8) veces la frecuencia de muestreo que se pretende conseguir en el conversor digital-analógico.

Así, si se sabe que las señales de audio no van a una frecuencia mayor de 10kHz, se muestrean en 8 bits, y hay 2 señales para multiplexar, la frecuencia mínima que se necesita en el DAC (y en este módulo) es de 10000 * 2^8 * 2 = 5.12 MHz.
Lo mismo digo. Aunque esto es algo más o menos "evidente" (nótense las comillas ;) ) siempre bien bien saber la teoría.
:gracias!:

Responder