使用Python、Numpy数组和WAVE模块编写WAV文件

mir*_*oft 5 python numpy wave

我正在尝试实现 Karplus-Strong 算法。

当我播放(通过 Jupyter Notebook 使用Audio(y,rate=Fs))收集的 numpy 数组(代表吉他协奏曲)时,一切看起来都很好。

不幸的是,使用 WAVE 模块将 numpy 数组:y写入 wav 文件是不正确的(使用下一个 python 代码):

noise_output = wave.open('k-s.wav', 'w')
noise_output.setparams((1, 4, Fs, 0, 'NONE', 'not compressed'))

for i in range(0, len(y)):
     value = y[i]
     packed_value = struct.pack('f', value)
     noise_output.writeframes(packed_value)

noise_output.close()
Run Code Online (Sandbox Code Playgroud)

y的每个元素是

<type 'numpy.float64'>
Run Code Online (Sandbox Code Playgroud)

我应该如何修改写入循环才能正确写入WAV文件?

有关该问题的更多信息。在写入 WAV 之前,y 数组的第一个元素是:

 [ 0.33659756  0.33659756 -0.43915295 -0.87036152  1.40708988  0.32123558
-0.6889402   1.9739982  -1.29587159 -0.12299964  2.18381762  0.82228042
 0.24593503 -1.28067426 -0.67568838 -0.01843234 -1.830472    1.2729578
-0.56575346  0.55410736]
Run Code Online (Sandbox Code Playgroud)

将元素写入 WAV 文件后,关闭 WAV 文件并再次读取它,我得到了收集数组的前 20 个元素:

[ 1051481732  1051481732 -1092560728 -1084305405  1068768133  1050966269
 -1087349149  1073523705 -1079648481 -1107564740  1074512811  1062371576
  1048303204 -1079775966 -1087571478 -1130954901 -1075163928  1067642952
 -1089415880  1057872379]
Run Code Online (Sandbox Code Playgroud)

sim*_*lmx 9

以下是使用标准库编写(立体声)波形文件的代码示例wave。我提供了两个示例:一个使用numpy,另一个不需要任何依赖项。

使用 numpy 数组

请注意,如果您的数据位于 numpy 数组中,则不需要该struct库。

import wave
import numpy as np

samplerate = 44100

# A note on the left channel for 1 second.
t = np.linspace(0, 1, samplerate)
left_channel = 0.5 * np.sin(2 * np.pi * 440.0 * t)

# Noise on the right channel.
right_channel = np.random.random(size=samplerate)

# Put the channels together with shape (2, 44100).
audio = np.array([left_channel, right_channel]).T

# Convert to (little-endian) 16 bit integers.
audio = (audio * (2 ** 15 - 1)).astype("<h")

with wave.open("sound1.wav", "w") as f:
    # 2 Channels.
    f.setnchannels(2)
    # 2 bytes per sample.
    f.setsampwidth(2)
    f.setframerate(samplerate)
    f.writeframes(audio.tobytes())

Run Code Online (Sandbox Code Playgroud)

使用列表

这是(几乎)相同的代码,但没有使用numpy. 不需要外部依赖。

import math
import random
import struct
import wave

samplerate = 44100

left_channel = [
    0.5 * math.sin(2 * math.pi * 440.0 * i / samplerate) for i in range(samplerate)
]
right_channel = [random.random() for _ in range(samplerate)]

with wave.open("sound2.wav", "w") as f:
    f.setnchannels(2)
    f.setsampwidth(2)
    f.setframerate(samplerate)
    for samples in zip(left_channel, right_channel):
        for sample in samples:
            sample = int(sample * (2 ** 15 - 1))
            f.writeframes(struct.pack("<h", sample))
Run Code Online (Sandbox Code Playgroud)


小智 8

import scipy.io.wavfile
scipy.io.wavfile.write("karplus.wav", Fs, y)
Run Code Online (Sandbox Code Playgroud)

田田!AFAIK 适用于 float64 和 float32,可能还有其他。对于立体声,形状必须为 (nb_samples, 2)。请参阅scipy.io.wavfile.write