python《多媒体技术与应用》实验报告「数字音频处理」

Posted Khalil三省

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python《多媒体技术与应用》实验报告「数字音频处理」相关的知识,希望对你有一定的参考价值。

 《多媒体技术与应用》实验报告

实验名称

数字视频处理

实验时间

2022/4/25

姓名

班级

计非201

学号

成绩

一.  实验目的

1.掌握数字音频的读取与打开;

2.掌握数字音频信号的频谱分析;

3.验证 PCM 编码算法。

二.实验原理

声音是由物体振动而产生的,声波的三要素是频率、振幅和波形,频率代表音阶的高低, 振幅代表响度(音量),波形代表音色,采样频率越高所能描述的声波频率就越高。采样率决定声音频率的范围(相当于音调),可以用数字波形表示。以波形表示的频率范围通常被称为带宽。

采样频率是单位时间内对媒体对象的采样次数,单位为赫兹 Hz。采样频率是指录音设备在一秒钟内对声音信号的采样次数,采样频率越高声音的还原就越真实越自然。脉冲编码调制(PCMPulse Code Modulation)在通信系统中完成将语音信号数字化功能。是一种对模拟信号数字化的取样技术,将模拟信号变换为数字信号的编码方式,特别是对于音频信号。

PCM 的实现主要包括三个步骤完成:抽样、量化、编码。分别完成时间上离散、幅度上离散、及量化信号的二进制表示。根据 CCITT 的建议,为改善小信号量化性能,采用压扩非均匀量化,有两种建议方式,分别为 A 律和 m 律方式,本设计采用了 A 律方式。

三.实验内容与关键步骤

1. 打开音频信号文件,获取音高、音量等信息;

2. 对打开的文件进行频谱分析;

3. 验证 PCM 算法。

四.代码

4-1 音量

import math
import wave
import pylab as pl
import numpy as np


# method 1: absSum
def calVolume(waveData, frameSize, overLap):
    wlen = len(waveData)
    step = frameSize - overLap
    frameNum = int(math.ceil(wlen * 1.0 / step))
    volume = np.zeros((frameNum, 1))
    for i in range(frameNum):
        curFrame = waveData[np.arange(i * step, min(i * step + frameSize, wlen))]
        curFrame = curFrame - np.median(curFrame)  # zero-justified
        volume[i] = np.sum(np.abs(curFrame))
    return volume


# method 2: 10 times log10 of square sum
def calVolumeDB(waveData, frameSize, overLap):
    wlen = len(waveData)
    step = frameSize - overLap
    frameNum = int(math.ceil(wlen * 1.0 / step))
    volume = np.zeros((frameNum, 1))
    for i in range(frameNum):
        curFrame = waveData[np.arange(i * step, min(i * step + frameSize, wlen))]
        curFrame = curFrame - np.mean(curFrame)  # zero-justified
        volume[i] = 10 * np.log10(np.sum(curFrame * curFrame))
    return volume


# ============ test the algorithm =============
# read wave file and get parameters.
fw = wave.open('sunday.wav', 'r')
params = fw.getparams()
print(params)
nchannels, sampwidth, framerate, nframes = params[:4]
strData = fw.readframes(nframes)
waveData = np.frombuffer(strData, dtype=np.int16)
waveData = waveData * 1.0 / max(abs(waveData))  # normalization
fw.close()

# calculate volume
frameSize = 256
overLap = 128
volume11 = calVolume(waveData, frameSize, overLap)
volume12 = calVolumeDB(waveData, frameSize, overLap)

# plot the wave
time = np.arange(0, nframes) * (1.0 / framerate)
time2 = np.arange(0, len(volume11)) * (frameSize - overLap) * 1.0 / framerate
pl.figure(figsize=(15, 9))
pl.subplot(311)
pl.plot(time, waveData)
pl.ylabel("Amplitude")
pl.subplot(312)
pl.plot(time2, volume11)
pl.ylabel("absSum")
pl.subplot(313)
pl.plot(time2, volume12, c="g")
pl.ylabel("Decibel(dB)")
pl.xlabel("time (seconds)")
pl.show()

4-2 音高

import wave
import numpy as np
import pylab as pl

# ============ test the algorithm =============
# read wave file and get parameters.
fw = wave.open('Ring08.wav', 'rb')
params = fw.getparams()
print(params)
nchannels, sampwidth, framerate, nframes = params[:4]
strData = fw.readframes(nframes)
# waveData = np.fromstring(strData, dtype=np.int16)
waveData = np.frombuffer(strData, np.int16)
waveData = waveData * 1.0 / max(abs(waveData))  # normalization
fw.close()

# plot the wave
time = np.arange(0, len(waveData)) * (1.0 / framerate)

index1 = 10000.0 / framerate
index2 = 10512.0 / framerate
index3 = 15000.0 / framerate
index4 = 15512.0 / framerate

pl.subplot(311)
pl.plot(time, waveData)
pl.plot([index1, index1], [-1, 1], 'r')
pl.plot([index2, index2], [-1, 1], 'r')
pl.plot([index3, index3], [-1, 1], 'g')
pl.plot([index4, index4], [-1, 1], 'g')
pl.xlabel("time (seconds)")
pl.ylabel("Amplitude")

pl.subplot(312)
pl.plot(np.arange(512), waveData[10000:10512], 'r')
pl.plot([59, 59], [-1, 1], 'b')
pl.plot([169, 169], [-1, 1], 'b')
print(1 / ((169 - 59) * 1.0 / framerate))
pl.xlabel("index in 1 frame")
pl.ylabel("Amplitude")

pl.subplot(313)
pl.plot(np.arange(512), waveData[15000:15512], 'g')
pl.xlabel("index in 1 frame")
pl.ylabel("Amplitude")
pl.show()

4-3 波形频谱

import librosa
import librosa.display
import matplotlib.pyplot as plt

# Load a wav file
y, sr = librosa.load('PCM.wav', sr=None)
# extract mel spectrogram feature
melspec = librosa.feature.melspectrogram(y, sr, n_fft=1024, hop_length=512, n_mels=128)
# convert to log scale
logmelspec = librosa.power_to_db(melspec)
plt.figure(figsize=(15, 10))
# plot a wavform
plt.subplot(2, 1, 1)
librosa.display.waveshow(y, sr)
plt.title('Beat wavform')
# plot mel spectrogram
plt.subplot(2, 1, 2)
librosa.display.specshow(logmelspec, sr=sr, x_axis='time', y_axis='mel')
plt.title('Mel spectrogram')
plt.tight_layout()  # 保证图不重叠
plt.show()

4-4 PCM

import numpy as np
import librosa
import matplotlib.pyplot as plt


def PCM_encode(x):
    n = len(x)
    out = np.zeros((n, 8))
    for i in range(n):
        # 符号位
        if x[i] > 0:
            out[i, 0] = 1
        else:
            out[i, 0] = 0
        # 数据位
        if abs(x[i]) < 32:
            out[i, 1], out[i, 2], out[i, 3], step, st = 0, 0, 0, 2, 0
        elif abs(x[i]) < 64:
            out[i, 1], out[i, 2], out[i, 3], step, st = 0, 0, 1, 2, 32
        elif abs(x[i]) < 128:
            out[i, 1], out[i, 2], out[i, 3], step, st = 0, 1, 0, 4, 64
        elif abs(x[i]) < 256:
            out[i, 1], out[i, 2], out[i, 3], step, st = 0, 1, 1, 8, 128
        elif abs(x[i]) < 512:
            out[i, 1], out[i, 2], out[i, 3], step, st = 1, 0, 0, 16, 256
        elif abs(x[i]) < 1024:
            out[i, 1], out[i, 2], out[i, 3], step, st = 1, 0, 1, 32, 512
        elif abs(x[i]) < 2048:
            out[i, 1], out[i, 2], out[i, 3], step, st = 1, 1, 0, 64, 1024
        else:
            out[i, 1], out[i, 2], out[i, 3], step, st = 1, 1, 1, 128, 2048

        if abs(x[i]) >= 4096:
            out[i, 1:] = np.array([1, 1, 1, 1, 1, 1])
        else:
            tmp = bin(int((abs(x[i]) - st) / step)).replace('0b', '')
            tmp = '0' * (4 - len(tmp)) + tmp
            t = [int(k) for k in tmp]
            out[i, 4:] = t
    return out.reshape(8 * n)


def PCM_decode(ins, v):
    inn = ins.reshape(len(ins) // 8, 8)
    slot = np.array([0, 32, 64, 128, 256, 512, 1024, 2048])
    step = np.array([2, 2, 4, 8, 16, 32, 64, 128])
    out = np.zeros(len(ins) // 8)
    for i in range(inn.shape[0]):
        sgn = 2 * inn[i, 0] - 1
        tmp = int(inn[i, 1] * 4 + inn[i, 2] * 2 + inn[i, 3])
        st = slot[tmp]
        dt = (inn[i, 4] * 8 + inn[i, 5] * 4 + inn[i, 6] * 2 + inn[i, 7]) * step[tmp] + 0.5 * step[tmp]
        out[i] = sgn * (st + dt) / 4096 * v
    return out


plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

data, sr = librosa.load('Ring08.wav')

sxx = np.array(list(map(int, data * 4096)))

y = PCM_encode(sxx)

yy = PCM_decode(y, 1)

plt.subplot(3, 1, 1)
plt.plot(data)
plt.title('编码前')

plt.subplot(3, 1, 2)
plt.plot(yy)
plt.title('解码后')

plt.subplot(3, 1, 3)
plt.plot(yy - data)
plt.title('误差')
plt.show()

五.   实验结果与分析

4-1 音量

aeiou.wav

sunday.wav

结果

 

 

4-2 音高

aeiou.wav

sunday.wav

Ring08.wav

结果

       

4-3 波形频谱

aeiou.wav

sunday.wav

PCM.wav

结果

4-4 PCM

PCM.wav

sunday.wav

Ring08.wav

结果

六.实验心得体会

通过本次实验,使我对于音频文件有了更深的理解,明白了音频的一些基本属性,如音高,音量等以及对于波形频谱的输出和PCM算法有了一定的认识.

FPGA与数字信号处理

 


过去十几年,通信与多媒体技术的快速发展极大地扩展了数字信号处理(DSP)的应用范围。眼下正在发生的是,以更高的速度和更低的成本实现越来越复杂的算法,这是针对高级信息服更高带宽以及增强的多媒体处理能力等需求的日益增加的结果。一些高性能应用正在不断发展,其中包括高级有线和无线音频、数据和视频处理。

通信和多媒体应用的发展,如互联网通信、安全无线通信以及消费娱乐设备,都在驱动着对能够有效实现复数运算和信号处理算法的高性能设备的需求。

这些应用中需要一些典型的DSP算法包括快速傅里叶变换(FFT)、离散余弦变换(DCT)、小波变换、数字滤波器(有限脉冲响应(FIR)、无限脉冲响应(IIR)和自适应滤波器)以及数字上下变频器。这些算法中,每一种都有一些结构性的元件可以用并行方法实现。而FPGA体系结构能够有效地实现并行运算。


数字滤波器:

数字滤波器通常用于修正和改变时域或频域中信号的特性。最为普通的数字滤波器就是线性时间不变(Linear Time-Invariant,LTI)滤波器。通常分为有限脉冲响应(FIR)和无限脉冲响应(IIR)两大类。

FIR滤波器:

有限长单位冲激响应滤波器,它可以在保证任意幅频特性的同时具有严格的线性相频特性,同时其单位抽样响应是有限长的,因而滤波器是稳定的系统。因此,FIR滤波器在通信、图像处理、模式识别等领域都有着广泛的应用。

FIR滤波处理如下式所示,其中x(n)为输入信号,h(n)为FIR滤波系数,y(n)为经过滤波后的信号;N表示FIR滤波器的抽头数,滤波器阶数为N-1。

由上式可得到FIR滤波器在FPGA中的实现结构,如图1所示,主要由延迟单元Z-1、乘法器和累加器组成。此结构为直接型FIR滤波器结构,也称横向结构(transverse)。

FIR结构如下:

FIR滤波器结构

FIR滤波器广泛应用于数字信号处理中,主要功能就是将不感兴趣的信号滤除,留下有用信号。FIR滤波器是全零点结构,系统永远稳定;并且具有线性相位的特征,在有效频率范围内所有信号相位上不失真。详细算法这里不多做介绍。

IIR滤波器:

IIR--无限脉冲响应滤波器,它的设计理念是根据所要设计滤波器的参数去确定一个模拟滤波器的传输函数,然后再根据这个传输函数,通过双线性变换、或脉冲响应不变法来进行数字滤波器的设计。

其实际为递归滤波器,顾名思义,具有反馈。

IIR数字滤波器采用递归型结构,即结构上带有反馈环路。IIR滤波器运算结构通常由延时、乘以系数和相加等基本运算组成,可以组合成直接型、正准型、级联型、并联型四种结构形式,都具有反馈回路。


其他数字信号处理方法:

离散傅里叶变换

自适应滤波器

最小二乘法

NTT高效卷积

NTT快速卷积

CIC滤波器

与数字信号处理相关的技术:

矩形变换与数论变换

差错控制和加密技术

调制以及解调


FPGA在数字信号处理(DSP)中的使用

在FPGA内实现DSP功能具有以下优点:

    • 性能提升

    • 设计实现灵活性提高

    • 系统级集成更高

通过一些设计调整的结合运用,基于FPGA的信号处理性能还可以获得进一步的提升。运算速度或者数据路径宽度都可以进一步提高,另外,时序操作可以在结构上增加一些并行度。这些措施中,每一种都可以提高一定的性能。在利用了目标FPGA器件灵活性的结构中实现算法,会获得比较大的好处。

利用FPGA,可以将多个设计功能集成到一个器件中。这种功能性的集成也可以提高性能、减小面积和功耗。

信号处理实现的另一个潜在的优点是,FPGA中包含一些预先验证过的信号处理算法单元。这些IP核或者块可以非常有效的实现一些常用的信号处理功能,使他们的性能达到最高。将多个高性能信号处理算法集成在一起,可以有效的降低成本、风险、,缩短开发时间。


设计考虑:

FPGA设计中一些注意事项对于下面列举的信号处理算法的实现非常重要。这些设计因素必须仔细的去实现,这样才能达到最高的性能,将设计实现的时间缩到最短。

    • 同步设计的实现

    • 模块化项目结构

    • 时钟边界转换

    • 时钟体系结构的实现

    • 关键时钟与控制信号的布线

    • 流水线深度和结构

    • 有效的设计约束

    • 信号处理算法架构的决策

    • 加入良好的调试功能

随着FPGA技术的进步,在FPGA中实现信号处理算法正在成为有吸引力的替代方案,其实现成本也很诱人。在FPGA中实现信号处理算法,传统上的限制正在硬件和软件设计层次上逐渐被克服。FPGA硬件结构正在实现增强的DSP块。并具有更多的功能和更强的性能。系统级设计软件正在简化从块级到硬件描述语言(HDL),级的转换。一些系统工具中集成了流行的DSP算法开发工具(例如MATLAB),大大简化了FPGA中实现信号处理算法的过程。


版权所有权归卿萃科技,转载请注明出处。

作者:卿萃科技ALIFPGA

原文地址:卿萃科技FPGA极客空间 微信公众号


 扫描二维码关注卿萃科技FPGA极客空间


 

 

以上是关于python《多媒体技术与应用》实验报告「数字音频处理」的主要内容,如果未能解决你的问题,请参考以下文章

FPGA与数字信号处理

全套完结数字电子技术基础——全套实验手册及仿真工艺实习建议保存

NJUPT Python编程及人工智能应用实验报告

《数字电子技术》——计时类应用设计报告

区块链技术与应用实验报告(实验五)

区块链技术与应用实验报告(实验五)