在此 notebook 中,我们将使用独立成分分析方法从三个观察结果中提取信号,每个观察结果都包含不同的原始混音信号。这个问题与 ICA 视频中解释的问题一样。
首先看看手头的数据集。我们有三个 WAVE 文件,正如我们之前提到的,每个文件都是混音形式。如果你之前没有在 python 中处理过音频文件,没关系,它们实际上就是浮点数列表。
首先加载第一个音频文件 ICA_mix_1.wav [点击即可聆听该文件]:
In [ ]:
import numpy as np
import wave
# Read the wave file
mix_1_wave = wave.open('ICA_mix_1.wav','r')
我们看看该 wave 文件的参数,详细了解该文件
In [ ]:
mix_1_wave.getparams()
该文件只有一个声道(因此是单声道)。帧率是 44100,表示每秒声音由 44100 个整数组成(因为文件是常见的 PCM 16 位格式,所以是整数)。该文件总共有 264515 个整数/帧,因此时长为:
In [ ]:
264515/44100
我们从该 wave 文件中提取帧,这些帧将属于我们将运行 ICA 的数据集:
In [ ]:
# Extract Raw Audio from Wav File
signal_1_raw = mix_1_wave.readframes(-1)
signal_1 = np.fromstring(signal_1_raw, 'Int16')
signal_1 现在是一个整数列表,表示第一个文件中包含的声音。
In [ ]:
'length: ', len(signal_1) , 'first 100 elements: ',signal_1[:100]
如果将此数组绘制成线形图,我们将获得熟悉的波形:
In [ ]:
import matplotlib.pyplot as plt
fs = mix_1_wave.getframerate()
timing = np.linspace(0, len(signal_1)/fs, num=len(signal_1))
plt.figure(figsize=(12,2))
plt.title('Recording 1')
plt.plot(timing,signal_1, c="#3ABFE7")
plt.ylim(-35000, 35000)
plt.show()
现在我们可以按照相同的方式加载另外两个 wave 文件 ICA_mix_2.wav 和 ICA_mix_3.wav
In [ ]:
mix_2_wave = wave.open('ICA_mix_2.wav','r')
#Extract Raw Audio from Wav File
signal_raw_2 = mix_2_wave.readframes(-1)
signal_2 = np.fromstring(signal_raw_2, 'Int16')
mix_3_wave = wave.open('ICA_mix_3.wav','r')
#Extract Raw Audio from Wav File
signal_raw_3 = mix_3_wave.readframes(-1)
signal_3 = np.fromstring(signal_raw_3, 'Int16')
plt.figure(figsize=(12,2))
plt.title('Recording 2')
plt.plot(timing,signal_2, c="#3ABFE7")
plt.ylim(-35000, 35000)
plt.show()
plt.figure(figsize=(12,2))
plt.title('Recording 3')
plt.plot(timing,signal_3, c="#3ABFE7")
plt.ylim(-35000, 35000)
plt.show()
读取所有三个文件后,可以通过 zip 运算创建数据集。
X
In [ ]:
X = list(zip(signal_1, signal_2, signal_3))
# Let's peak at what X looks like
X[:10]
现在准备运行 ICA 以尝试获取原始信号。
In [ ]:
# TODO: Import FastICA
# TODO: Initialize FastICA with n_components=3
# TODO: Run the FastICA algorithm using fit_transform on dataset X
In [ ]:
ica_result.shape
我们将其拆分为单独的信号并查看这些信号
In [ ]:
result_signal_1 = ica_result[:,0]
result_signal_2 = ica_result[:,1]
result_signal_3 = ica_result[:,2]
我们对信号进行绘制,查看波浪线的形状
In [ ]:
# Plot Independent Component #1
plt.figure(figsize=(12,2))
plt.title('Independent Component #1')
plt.plot(result_signal_1, c="#df8efd")
plt.ylim(-0.010, 0.010)
plt.show()
# Plot Independent Component #2
plt.figure(figsize=(12,2))
plt.title('Independent Component #2')
plt.plot(result_signal_2, c="#87de72")
plt.ylim(-0.010, 0.010)
plt.show()
# Plot Independent Component #3
plt.figure(figsize=(12,2))
plt.title('Independent Component #3')
plt.plot(result_signal_3, c="#f65e97")
plt.ylim(-0.010, 0.010)
plt.show()
某些波浪线看起来像音乐波形吗?
确认结果的最佳方式是聆听生成的文件。另存为 wave 文件并进行验证。在此之前,我们需要:
In [ ]:
from scipy.io import wavfile
# Convert to int, map the appropriate range, and increase the volume a little bit
result_signal_1_int = np.int16(result_signal_1*32767*100)
result_signal_2_int = np.int16(result_signal_2*32767*100)
result_signal_3_int = np.int16(result_signal_3*32767*100)
# Write wave files
wavfile.write("result_signal_1.wav", fs, result_signal_1_int)
wavfile.write("result_signal_2.wav", fs, result_signal_2_int)
wavfile.write("result_signal_3.wav", fs, result_signal_3_int)
现在生成的文件包括:[注意:确保先调低音响设备的音量,以防某些问题导致文件听起来像静态的]
音乐: