Colorir uma forma de onda com centróide espectral ou por outros meios


8

Atualização 8

Insatisfeito por ter que fazer o upload de faixas para o serviço e olhar para o novo lançamento do RekordBox 3, decidi dar uma nova olhada em uma abordagem offline e em uma resolução mais precisa: D

Parece promissor, embora ainda esteja em um estado muito alfa:

Johnick - Good Time

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Observe que não há escala logarítmica nem ajuste de paleta, apenas um mapeamento bruto da frequência para o HSL.

A idéia : agora um renderizador de forma de onda tem um provedor de cores que é consultado por uma cor para uma posição específica. O que você está vendo acima obtém a taxa de cruzamento zero para as 1024 amostras próximas a essa posição.

Obviamente, ainda há muito o que fazer antes de obter algo robusto, mas parece um bom caminho ...

Do RekordBox 3 :

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Atualização 7

A forma final que adotarei, assim como na atualização 3

insira a descrição da imagem aqui

(foi um pouco de Photoshop para obter transições suaves entre cores)

A conclusão é que eu estava perto meses atrás, mas não considerou esse resultado pensando que era ruim X)

Atualização 6

Eu descobri o projeto recentemente, então pensei em atualizar aqui: D

Música: Chic - Good Times 2001 (mix do Stonebridge Club)

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

É IMO muito melhor, as batidas têm uma cor constante, etc ... não é otimizado.

Como ?

Ainda com http://developer.echonest.com/docs/v4/_static/AnalyzeDocumentation.pdf (página 6)

Para cada segmento:

public static int GetSegmentColorFromTimbre(Segment[] segments, Segment segment)
{
    var timbres = segment.Timbre;

    var avgLoudness = timbres[0];
    var avgLoudnesses = segments.Select(s => s.Timbre[0]).ToArray();
    double avgLoudnessNormalized = Normalize(avgLoudness, avgLoudnesses);

    var brightness = timbres[1];
    var brightnesses = segments.Select(s => s.Timbre[1]).ToArray();
    double brightnessNormalized = Normalize(brightness, brightnesses);

    ColorHSL hsl = new ColorHSL(brightnessNormalized, 1.0d, avgLoudnessNormalized);
    var i = hsl.ToInt32();
    return i;
}

public static double Normalize(double value, double[] values)
{
    var min = values.Min();
    var max = values.Max();
    return (value - min) / (max - min);
}

Obviamente, há muito mais código necessário antes de você chegar aqui (fazer o upload para o serviço, analisar JSON etc.), mas esse não é o objetivo deste site, por isso estou postando o material relevante para obter o resultado acima.

Então, eu estou usando as 2 primeiras funções do resultado da análise, certamente há mais a ver com isso, mas ainda preciso testar. Se algum dia encontrar algo mais legal do que o anterior, voltarei e atualizarei aqui.

Como sempre, qualquer dica sobre o tema é bem-vinda!

Atualização 5

Algum gradiente usando séries harmônicas

insira a descrição da imagem aqui

A suavização das cores é sensível à proporção, caso contrário, parece ruim, precisará de alguns ajustes.

Atualização 4

Reescreva a coloração que ocorrerá na origem e nas cores suavizadas usando um filtro Alpha beta com valores de 0,08 e 0,02.

insira a descrição da imagem aqui

Um pouco melhor quando diminui o zoom

insira a descrição da imagem aqui

O próximo passo é obter uma ótima paleta de cores!

Atualização 3

insira a descrição da imagem aqui

Amarelos representam médiuns insira a descrição da imagem aqui

Ainda não é tão bom quando não está sendo usado. insira a descrição da imagem aqui

(a paleta precisa de um trabalho sério)

Atualização 2

Teste preliminar usando a segunda dica de coeficiente 'timbre' de pichenettes insira a descrição da imagem aqui

Atualização 1

Um teste preliminar usando um resultado de análise do serviço EchoNest , observe que ele não está alinhado muito bem (minha culpa), mas é muito mais coerente do que a abordagem acima.

insira a descrição da imagem aqui

Para pessoas interessadas em usar essa excelente API, comece aqui: http://developer.echonest.com/docs/v4/track.html#profile

Além disso, não se confunda com essas formas de onda, pois representam 3 músicas diferentes.

Questão inicial

Até agora, esse é o resultado que eu recebo usando uma FFT de 256 amostras e calculando o centróide espectral de cada pedaço .

Resultado bruto dos cálculos insira a descrição da imagem aqui

Alguma suavização aplicada (o formulário fica muito melhor com ele) insira a descrição da imagem aqui

Forma de onda produzida insira a descrição da imagem aqui

Idealmente, é assim que deve ser (tirada do software Serato DJ ) insira a descrição da imagem aqui

Você sabe qual técnica / algoritmo eu poderia usar para poder dividir o áudio quando a frequência média muda com o tempo? (como na imagem acima)


11
Eu acho que você está no caminho certo usando o centróide espectral; talvez você precise apenas de um mapeamento não linear do resultado para obter uma boa distribuição de cores. Parece que apenas o segmento azul / ciano da sua paleta está sendo usado atualmente.
Pichenettes

11
Sua pergunta é sobre o algoritmo de pseudo-cor ou sobre como dividir o áudio em partes de maneira automatizada?
Bjorn Roche 5/05

@ pichenettes: certo, vou resolver esse problema usando uma escala logarítmica.
aybe

11
É exatamente isso que o freesound.org usa para colorir suas formas de onda. Veja o spectral_centroidcódigo deles . O que eu realmente gostaria é mapear o espectro de áudio no espectro de cores, para que a baixa frequência seja vermelha, a alta frequência seja azul, a combinação de ambas é magenta, a frequência média é verde, a varredura de log é arco-íris, o ruído branco é branco, o ruído rosa é rosa, o ruído vermelho é vermelho ... Não consigo descobrir como fazê-lo, uma vez que um espectro é linear e o outro é log. :) flic.kr/p/7S8oHA
endolith

11
@Sim: Sim, eu sei como fazer uma varredura de log parecer um arco-íris, mas quando medido com espaçamento de frequência de log (faixas de largura proporcional), o ruído branco tem um espectro inclinado, não um espectro plano, portanto não produziria luz branca . Nossos nomes para cores de ruído são baseados em bandas de largura constante (espaçamento linear), mas nossa percepção de tons está em um espaçamento de log (bandas de largura proporcional). Posso perguntar o que você planeja fazer quando o fizer funcionar?
Endolith

Respostas:


4

Você pode tentar primeiro o seguinte (sem segmentação):

  • Processe o sinal em pequenos pedaços (digamos 10 ms a 50 ms de duração) - se necessário, com uma sobreposição de 50% entre eles.
  • Calcule o centróide espectral em cada pedaço.
  • Aplique uma função não linear ao valor do centróide espectral para obter uma distribuição uniforme da cor da paleta usada. O logaritmo é um bom começo. Outra opção é calcular primeiro a distribuição do valor do centróide e o arquivo inteiro e depois colorir de acordo com os percentis dessa distribuição ( CDF ). Essa abordagem adaptativa garante que cada cor da paleta seja usada na mesma proporção. A desvantagem é que o que é plotado em azul em um arquivo não será semelhante ao que é plotado em azul em outro arquivo se essa abordagem adaptativa for usada!

Não está claro pela imagem se o Serato faz isso, ou de fato vai um passo além e tenta segmentar o sinal - pode não ser surpreendente, pois conhecer os instantes em que as notas estão presentes em um sinal de música pode ajudar a sincronizá-los. ! Os passos seriam:

  • Calcule uma transformada de Fourier de curto prazo (espectrograma) do sinal - usando a FFT em segmentos curtos e sobrepostos (comece com um tamanho de FFT de 1024 ou 2048 com áudio de 44,1kHz).
  • Calcule uma função de detecção de onset. Eu recomendo que você analise este documento - a abordagem proposta é muito eficaz e até mesmo uma implementação em C ++ leva menos de 10 linhas. Você pode encontrar uma implementação no Yaafe - as ComplexDomainOnsetDetection.
  • Detecte picos na função de detecção de início para obter a posição dos ajustes das notas.
  • Calcule o centróide espectral em todos os segmentos de tempo delimitados pelos onets detectados (não se esqueça de exibir a janela e / ou zero-pad!)
  • E não se esqueça do mapa não linear! Observe que o efeito de gradiente que aparece entre cada nota na forma de onda Serato pode ser gerado artificialmente.

Depois que você obtiver esse trabalho, um "resultado final" seria calcular alguns outros recursos em cada segmento (momentos, um punhado de MFCCs ...), executar k-means nesses vetores de recursos e decidir a cor de o segmento usando o índice de cluster. Veja a seção II do artigo de Ravelli .


Comecei a trabalhar na sua solução número 2, felizmente o serviço (EchoNest) que estou usando fornece detecção de onset em suas análises, o que é uma ótima notícia e uma economia em tempo real! Atualizei minha resposta com um pequeno teste que fiz e parece promissor (observe que não está alinhado corretamente, pois é muito rápido e sujo). Vou postar um resultado melhor quando tiver feito um progresso significativo. Obrigado !
Aybe 5/05

11
Então você não tem nenhum trabalho a fazer. O segundo coeficiente "timbre" na análise EchoNest está muito relacionado ao centróide, portanto você não tem nenhum cálculo a fazer (a menos que eles se livrem do componente DC em sua base; nesse caso, é o primeiro coeficiente) - basta usar o valor de batida ou de nível de segmento do vetor "timbre".
pichenettes 5/05

11
O "brilho" medido pelo segundo coeficiente "timbre" na análise EN está muito relacionado ao centróide espectral (a diferença é que o analisador EchoNest usa algum pré-processamento perceptivo - filtragem da orelha média, mascaramento de tempo / frequência - em vez de FFT bruto). O código de cores usando a bandeja máxima no vetor 'pitch' seria útil para material melódico monofônico e muito puro, mas é bastante sem sentido para um loop de bateria.
Pichenettes

11
Ubounded? Ainda é limitado pela energia do sinal no quadro analisado ... Acho que para esse recurso vale a pena manter a escala consistente entre as faixas. O que eu faria: colecionava uma dúzia de músicas muito diversas para ter uma ideia da distribuição do valor. Se necessário, aplique um mapa não linear simples para torná-lo mais gaussiano. Em seguida, remova a média e divida pelo desvio padrão. Em seguida, aplique atan para torná-lo delimitado - trazendo de volta os valores discrepantes para o primeiro ou nono decil sem causar cortes.
Pichenettes

11
Quando a forma de onda é reduzida, segmente seu sinal de acordo com elementos maiores, como barras ou seções - em vez de tentar colorir notas / batidas individuais.
pichenettes
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.