【代码复现|matlab】一种音频信号转换视觉颜色信息的方法及系统

本文介绍了一种专利方法,通过音频信号的采样、傅里叶变换和颜色空间转换,将音频数据转化为HSV色彩空间,进而生成连续变化的颜色。详细步骤包括能量计算、频率矩阵处理和RGB值计算。通过示例代码展示了如何将音乐文件转换为实时颜色变化,并展示了转换前后的效果图。
摘要由CSDN通过智能技术生成

专利对应:《一种音频信号转换视觉颜色信息的方法及系统》

该专利的主要步骤如下:

1. 对原始音频信号进行采样,得到若干音频块,对每个音频块:

2. 根据块的平均能量得到变量V,表示亮度;

3. 对块进行傅里叶变换后,得到频率矩阵f和幅度谱F;

4. 根据公式将频率矩阵转换为矩阵H,用于表示色相;

5. 对幅度谱矩阵归一化,得到矩阵S,用于表示饱和度,此时HSV颜色空间三个维度的值均已获得;

6. 根据色相,计算块内每个信号对应的RGB值;

7. 计算块内所有信号的平均RGB值,作为这个块的颜色。

通过audioread("")函数可以得到两个结果,分别是n*1的离散音频数据audio,和 采样率sampHz。采样率表达了每秒从原始音频中采样得到的离散数据的数量,即audio中每sampHz个数据是在一秒内。

[audio,sampHz] = audioread("music.mp3");

接下来,我们对数据audio采样成若干个m*1大小的数据块audioBlock。最终每个数据块生成一个颜色,为了使人眼难以捕捉到变化,我们使每秒颜色变化30次,即刷新率为30Hz,对应m取值为n/30.

rate = 30; %每秒颜色刷新次数
% 分块大小
sampSize = sampHz / rate;

第t个块数据可以由索引得到:

audioBlock = audio(t*sampSize + 1: (t + 1) * sampSize);

计算平均平方能量如下,对应亮度V表示为其与预设的最大平均平方能量之比。

E = \frac{1}{N}\sum_i{I_i}^2

V = \frac{E}{E_{max}}

maxE = 0.1;
avgE = mean(audioBlock.^2);
V = avgE / maxE;

对audioBlock进行傅里叶变换,得到幅度谱audioFF,对应的饱和度矩阵S为其归一化后的结果:

    audioF = fft(audioBlock);
  
    audioFF = abs(audioF);
    S = (audioFF - min(audioFF)) / (max(audioFF) - min(audioFF));

根据专利所述,色相H和仅频率有关。傅里叶变换后的各个频率值可以根据索引的映射关系得到:

f_j = j * \frac{sampHz}{sampSize}

由于傅里叶变换后的频率左右对称,因此只计算左侧频率,然后反转拼接得到频率矩阵:

    audioF = fft(audioBlock);
    for j = 1:sampSize / 2 %频率左右对称,因此只计算左边的频率
        f_left(j) = j * rate;
    end
    f = [f_left, f_left(end : -1 : 1)];

根据专利所述,他们排除了色相中红色到紫色段(色相对应270°到360°),对20000Hz映射到0-270°这个颜色范围上:

H = \frac{270}{20000HZ}f

 H = f * 270 / 2e4;

根据HSV转RGB公式,我们得到audioBlock中的每个RGB值,储存在RGB矩阵中:,最后改矩阵的均值即这个audioBlock的整体颜色:

 

    RGB = zeros(sampSize, 3); % sampSize 行 3 列
    for j = 1 : sampSize
        switch(Hk(j))
            case 0 
                RGB(j,:) = [V, tt(j), p(j)]; 
            case 1
                RGB(j,:) = [q(j), V, p(j)]; 
            case 2
                RGB(j,:) = [p(j), V, tt(j)];
            case 3
                RGB(j,:) = [p(j), q(j), V];
            case 4
                RGB(j,:) = [tt(j), p(j), V];
            case 5
                RGB(j,:) = [V, p(j), q(j)];
        end
    end
    avgRGB = mean(RGB,1); %每列均值

注意,matlab语法中switch-case不需要break.

完整代码:


clear all
clc
[audio,sampHZ] = audioread("Notification.wav");
% 取第一个声道的前1000帧信息
audio = audio(1:sampHZ*3,1);
% 此时audio是1*n的矩阵
rate = 100;
% 分块
sampSize = sampHZ/rate;
t = 0;
showRGB = uint8(zeros(30,3*rate,3));
maxE = 255 * 255 * 0.3;% 假设audio中所有元素值位于0-1之间
for i = 1: sampSize : length(audio)
    %得到没一个长度为sampSize的块
    %未进行重采样
    audioBlock = audio(t*sampSize + 1: (t + 1) * sampSize);
    % 计算块内平均能量
    avgE = mean(audioBlock.^2);
    %亮度
%     V = avgE / maxE;
    V = 1;
    % 频谱
    audioF = fft(audioBlock);
    for j = 1:sampSize / 2 %频率左右对称,因此只计算左边的频率
        f_left(j) = j * rate;
    end
    f = [f_left, f_left(end : -1 : 1)];
    H = f * 270 / 2e4;
    
    % 幅度谱
    audioFF = abs(audioF);
    S = (audioFF - min(audioFF)) / (max(audioFF) - min(audioFF));
    Hk =  uint8(mod (floor(H/60),6));
    ff = H/60 - double(Hk);
    ff= ff';
    %S  = S.^0.5;
    p = V .* (1 - S);
    q = V .* (1 - ff.*S);
    tt = V .* (1 - (1 - ff) .*S);
    % 计算对应的均值
    RGB = zeros(sampSize, 3); % sampSize 行 3 列
    for j = 1 : sampSize
        switch(Hk(j))
            case 0 
                RGB(j,:) = [V, tt(j), p(j)]; 
            case 1
                RGB(j,:) = [q(j), V, p(j)]; 
            case 2
                RGB(j,:) = [p(j), V, tt(j)];
            case 3
                RGB(j,:) = [p(j), q(j), V];
            case 4
                RGB(j,:) = [tt(j), p(j), V];
            case 5
                RGB(j,:) = [V, p(j), q(j)];
        end
    end
    avgRGB = mean(RGB,1); %每列均值
    avgRGB = abs(avgRGB * 255 ); %转为uint8,便于转为16进制
    showRGB(:,t+1,1) = avgRGB(1);
    showRGB(:,t+1,2) = avgRGB(2);
    showRGB(:,t+1,3) = avgRGB(3);
    t = t + 1;
end

subplot(311),plot(audio)
subplot(312),plot(log(abs(fft(audio)+1)))
subplot(313),imshow(showRGB)

效果:

图1:振幅-时间图

图2:完整音频频谱图

图3:颜色-时间图 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值