with ultimate transcribe the sound recognition language guide python matlab signal-processing pitch-tracking audio-analysis

ultimate - speaker recognition python



Cómo convertir una pista de tono desde un algoritmo de extracción de melodías a una señal de audio zumbante (3)

Aunque no tengo acceso a su función synth (), en función de los parámetros que tome, diría que su problema es porque no está manejando la fase.

Es decir, no es suficiente concatenar fragmentos de forma de onda, debe asegurarse de que tengan fase continua. De lo contrario, estás creando una discontinuidad en la forma de onda cada vez que concatenas dos fragmentos de forma de onda. Si este es el caso, supongo que estás escuchando la misma frecuencia todo el tiempo y que suena más a diente de sierra que a sinusoide, ¿estoy en lo cierto?

La solución es establecer la fase de inicio de snippet n en la fase final del fragmento n-1. Aquí hay un ejemplo de cómo concatenaría dos formas de onda con diferentes frecuencias sin crear una discontinuidad de fase:

fs = 44100; % sampling frequency % synthesize a cosine waveform with frequency f1 and starting additional phase p1 p1 = 0; dur1 = 1; t1 = 0:1/fs:dur1; x1(1:length(t1)) = 0.5*cos(2*pi*f1*t1 + p1); % Compute the phase at the end of the waveform p2 = mod(2*pi*f1*dur1 + p1,2*pi); dur2 = 1; t2 = 0:1/fs:dur2; x2(1:length(t2)) = 0.5*cos(2*pi*f2*t2 + p2); % use p2 so that the phase is continuous! x3 = [x1 x2]; % this should give you a waveform without any discontinuities

Tenga en cuenta que, si bien esto le proporciona una forma de onda continua, la transición de frecuencia es instantánea. Si desea que la frecuencia cambie gradualmente de time_n a time_n + 1, tendrá que usar algo más complejo como la interpolación McAulay-Quatieri. Pero en cualquier caso, si tus fragmentos son lo suficientemente cortos, esto debería sonar lo suficientemente bueno.

Respecto a otros comentarios, si entiendo correctamente tu objetivo es solo poder escuchar la secuencia de frecuencia, no para que suene como la fuente original. En este caso, la amplitud no es tan importante y puedes mantenerla fija.

Si quisieras que suene como la fuente original, esa es una historia completamente diferente y, probablemente, más allá del alcance de esta discusión.

¡Espero que esto responda a su pregunta!

Como parte de un proyecto de investigación de diversión en el hogar, estoy tratando de encontrar una forma de reducir / convertir una canción en una señal de audio zumbante (la melodía subyacente que los humanos percibimos cuando escuchamos una canción). Antes de continuar describiendo mi intento sobre este problema, me gustaría mencionar que soy totalmente nuevo en el análisis de audio, aunque tengo mucha experiencia en el análisis de imágenes y videos.

Después de buscar en Google un poco, encontré un montón de algoritmos de extracción de melodías. Dada una señal de audio polifónica de una canción (ej .: archivo .wav), emiten una pista de tono --- en cada punto estiman el tono dominante (proveniente de la voz de un cantante o algún instrumento que genere melodía) y rastrean el dominante lanzar con el tiempo.

Leí algunos documentos, y parecen calcular una transformación de Fourier de la canción de corta duración, y luego hacer algunos análisis sobre el espectrograma para obtener y rastrear el tono dominante. La extracción de melodías es solo un componente en el sistema que estoy tratando de desarrollar, así que no me importa usar ningún algoritmo que esté disponible en lo que respecta a un trabajo decente en mis archivos de audio y el código está disponible. Como soy nuevo en esto, me complacerá escuchar cualquier sugerencia sobre qué algoritmos se sabe que funcionan bien y dónde puedo encontrar su código.

Encontré dos algoritmos:

  1. Yaapt pitch tracking
  2. Melodia

Elegí Melodia ya que los resultados en diferentes géneros musicales parecían bastante impresionantes. Por favor revisa esto para ver sus resultados . El zumbido que escuchas por cada pieza de música es esencialmente lo que me interesa.

"Es la generación de este zumbido para cualquier canción arbitraria, con la que quiero tu ayuda en esta cuestión".

El algoritmo (disponible como plugin de vamp) genera una pista de pitch --- [time_stamp, pitch / frequency] --- una matriz Nx2 donde en la primera columna está la marca de tiempo (en segundos) y la segunda columna es dominante detectado en el sello de tiempo correspondiente. A continuación se muestra una visualización de la pista de tono obtenida del algoritmo superpuesto en color púrpura con la señal de dominio de tiempo de una canción (arriba) y su espectrograma / corto-tiempo-fourier. Los valores negativos de tono / frecuencia representan la estimación de tono dominante de los algoritmos para los segmentos no sonoros / no melódicos. Entonces todas las estimaciones de tono> = 0 corresponden a la melodía, el resto no es importante para mí.

Ahora quiero convertir esta pista de pitch en una señal de audio zumbante, como los autores lo tienen en su sitio web.

A continuación se muestra una función de MATLAB que escribí para hacer esto:

function [melSignal] = melody2audio(melody, varargin) % melSignal = melody2audio(melody, Fs, synthtype) % melSignal = melody2audio(melody, Fs) % melSignal = melody2audio(melody) % % Convert melody/pitch-track to a time-domain signal % % Inputs: % % melody - [time-stamp, dominant-frequency] % an Nx2 matrix with time-stamp in the % first column and the detected dominant % frequency at corresponding time-stamp % in the second column. % % synthtype - string to choose synthesis method % passed to synth function in synth.m % current choices are: ''fm'', ''sine'' or ''saw'' % default=''fm'' % % Fs - sampling frequency in Hz % default = 44.1e3 % % Output: % % melSignal -- time-domain representation of the % melody. When you play this, you % are supposed to hear a humming % of the input melody/pitch-track % p = inputParser; p.addRequired(''melody'', @isnumeric); p.addParamValue(''Fs'', 44100, @(x) isnumeric(x) && isscalar(x)); p.addParamValue(''synthtype'', ''fm'', @(x) ismember(x, {''fm'', ''sine'', ''saw''})); p.addParamValue(''amp'', 60/127, @(x) isnumeric(x) && isscalar(x)); p.parse(melody, varargin{:}); parameters = p.Results; % get parameter values Fs = parameters.Fs; synthtype = parameters.synthtype; amp = parameters.amp; % generate melody numTimePoints = size(melody,1); endtime = melody(end,1); melSignal = zeros(1, ceil(endtime*Fs)); h = waitbar(0, ''Generating Melody Audio'' ); for i = 1:numTimePoints % frequency freq = max(0, melody(i,2)); % duration if i > 1 n1 = floor(melody(i-1,1)*Fs)+1; dur = melody(i,1) - melody(i-1,1); else n1 = 1; dur = melody(i,1); end % synthesize/generate signal of given freq sig = synth(freq, dur, amp, Fs, synthtype); N = length(sig); % augment note to whole signal melSignal(n1:n1+N-1) = melSignal(n1:n1+N-1) + reshape(sig,1,[]); % update status waitbar(i/size(melody,1)); end close(h); end

La lógica subyacente detrás de este código es la siguiente: en cada marca de tiempo, sintetizo una onda de corta duración (digamos una onda sinusoidal) con una frecuencia igual a la frecuencia / tono dominante detectado en esa marca de tiempo por una duración igual a su espacio con la próxima marca de tiempo en la matriz de entrada de melodía. Solo me pregunto si estoy haciendo esto bien.

Luego tomo la señal de audio que obtengo de esta función y la toco con la canción original (melodía en el canal izquierdo y canción original en el canal derecho). Aunque la señal de audio generada parece segmentar bastante bien las fuentes generadoras de melodía (voz / instrumento de plomo), está activa donde la voz es cero en todas partes, la señal en sí misma está lejos de ser un zumbido (me sale algo así como beep beep beeeeep beep beeep beeeeeeeep) que los autores muestran en su sitio web. Específicamente, a continuación se muestra una visualización que muestra la señal del dominio del tiempo de la canción de entrada en la parte inferior y la señal del dominio del tiempo de la melodía generada usando mi función.

Uno de los principales problemas es que, aunque me da la frecuencia de la onda para generar en cada marca de tiempo y también la duración, no sé cómo establecer la amplitud de la onda. Por ahora, configuro la amplitud para que sea un valor constante / constante, y sospecho que aquí es donde está el problema.

¿Alguien tiene alguna sugerencia sobre esto? Acepto sugerencias en cualquier lenguaje de programa (preferiblemente MATLAB, python, C ++), pero supongo que mi pregunta aquí es más general --- ¿Cómo generar la onda en cada marca de tiempo?

Algunas ideas / soluciones en mi mente:

  1. Establezca la amplitud obteniendo una estimación promediada / máxima de la amplitud a partir de la señal de dominio de tiempo de la canción original.
  2. Cambie totalmente mi enfoque: calcule el espectrograma / transformada de Fourier de corta duración de la señal de audio de la canción. cortar casi / cero o suavemente todas las otras frecuencias excepto las de mi pista de tono (o están cerca de mi pista de tono). Y luego calcule la transformada de Fourier inversa a corto plazo para obtener la señal del dominio del tiempo.

Si entiendo correctamente, parece que ya tiene una representación precisa del tono, pero su problema es que lo que genera simplemente no "suena lo suficientemente bueno".

Comenzando con su segundo enfoque: filtrar cualquier cosa que no sea el tono no va a llevar a nada bueno. Al eliminar todo menos algunas ubicaciones de frecuencia correspondientes a las estimaciones de tono locales, perderá la textura de la señal de entrada, lo que hace que suene bien. De hecho, si llevaras eso a un extremo y eliminaras todo menos la muestra correspondiente al tono y tomaras un ifft, obtendrías exactamente una sinusoide, que es lo que estás haciendo actualmente. Si desea hacer esto de todos modos, le recomiendo que realice todo esto simplemente aplicando un filtro a su señal temporal en lugar de entrar y salir del dominio de la frecuencia, que es más costoso y engorroso. El filtro tendría un pequeño corte alrededor de la frecuencia que desea mantener y que permitiría un sonido con mejor textura también.

Sin embargo, si ya tiene estimaciones de tono y duración con las que está contento pero quiere mejorar la reproducción del sonido, le sugiero que simplemente reemplace sus ondas sinusoidales, lo que siempre sonará como un pitido tonto sin importar cuánto masajéelos con un poco de zumbido real (o violín o flauta o lo que quieras) muestras para cada frecuencia en la escala. Si la memoria es una preocupación o si las canciones que representa no caen en una escala bien templada (pensando en la canción de Oriente Medio, por ejemplo), en lugar de tener una muestra de zumbido para cada nota de la escala, solo podría tener muestras de zumbido para un pocas frecuencias. A continuación, derivaría los sonidos de zumbido a cualquier frecuencia haciendo una conversión de frecuencia de muestreo de una de estas muestras de zumbido. Tener algunas muestras para realizar la conversión de muestra le permitirá elegir la que se ajusta a la "mejor" relación con la frecuencia que necesita producir, ya que la complejidad de la conversión de muestreo depende de esa relación. Obviamente, agregar una conversión de frecuencia de muestreo sería más laborioso y exigente desde el punto de vista de la computación en comparación con solo tener un banco de muestras para elegir.

Usar un banco de muestras reales hará una gran diferencia en la calidad de lo que renderiza. También te permitirá tener ataques realistas para cada nueva nota que toques.

Entonces sí, como sugiere, puede querer jugar también con la amplitud siguiendo la amplitud instantánea de la señal de entrada para producir una representación más matizada de la canción.

Por último, también jugaría con las estimaciones de duración que tiene para que tenga transiciones más suaves de un sonido al siguiente. Adivinando por la interpretación de su archivo de audio que disfruté mucho (beep beep beeeeep beep beeep beeeeeeeep) y el gráfico que muestra, parece que tiene muchas interrupciones insertadas en la interpretación de su canción. Puede evitar esto ampliando las estimaciones de duración para deshacerse de cualquier silencio que sea más corto que, por ejemplo, 1 segundo. De esta forma, preservarías los silencios reales de la canción original, pero evitarás cortar cada nota de tu canción.


Tienes al menos 2 problemas.

En primer lugar, como suponía, su análisis ha desechado toda la información de amplitud de la parte de la melodía del espectro original. Necesitará un algoritmo que capture esa información (y no solo la amplitud de la señal completa para la entrada polifónica, o la de solo el intervalo de tono FFT para cualquier sonido musical natural). Este es un problema no trivial, en algún lugar entre la extracción de tono melódico y la separación de fuente ciega.

En segundo lugar, el sonido tiene timbre, incluidos sobretonos y sobres, incluso a una frecuencia constante. Su método de síntesis solo está creando una onda sinusoidal única, mientras que el zumbido probablemente crea un montón de armónicos más interesantes, incluidas muchas frecuencias más altas que solo el tono. Para un sonido un poco más natural, podrías intentar analizar el espectro de ti mismo tarareando un solo tono e intentar recrear todas esas docenas de ondas sinusoidales armónicas, en lugar de solo una, cada una con la amplitud relativa adecuada, al sintetizar cada frecuencia. en tu análisis También podría mirar la envolvente de amplitud a lo largo del tiempo tarareando una nota corta, y usar esa envolvente para modular la amplitud de su sintetizador.