我的程序将音乐速度降低了 50%,但仅在一个频道中

my program reduces music speed by 50% but only in one channel

我正在使用 python 中的 wave 库来尝试将音频速度降低 50%。我已经成功了,但只是在正确的渠道中。在左声道是一大堆静电。

import wave,os,math
r=wave.open(r"C:\Users\A\My Documents\LiClipse Workspace\Audio 
compression\Audio compression\aha.wav","r")
w=wave.open(r"C:\Users\A\My Documents\LiClipse Workspace\Audio 
compression\Audio compression\ahaout.wav","w")
frames=r.readframes(r.getnframes())
newframes=bytearray()
w.setparams(r.getparams())
for i in range(0,len(frames)-1):
    newframes.append(frames[i])
    newframes.append(frames[i])
w.writeframesraw(newframes)

这是为什么?因为我只是复制和粘贴原始数据,所以我肯定不能生成静态数据? 编辑:我一直在寻找年龄,我终于找到了波形格式的有用资源:http://soundfile.sapp.org/doc/WaveFormat/ 如果我想保留立体声,看起来我需要复制 4 的实际样本宽度两次。这是因为有两个通道,它们占用 4 个字节而不是 2 个。

`import wave
r=wave.open(r"C:\Users\A\My Documents\LiClipse Workspace\Audio 
compression\Audio compression\aha.wav","r")
w=wave.open(r"C:\Users\A\My Documents\LiClipse Workspace\Audio 
compression\Audio compression\ahaout.wav","w")
frames=r.readframes(r.getnframes())
newframes=bytearray()
w.setparams(r.getparams())
w.setframerate(r.getframerate())
print(r.getsampwidth())
for i in range(0,len(frames)-4,4):
    newframes.append(frames[i])
    newframes.append(frames[i+1])
    newframes.append(frames[i+2])
    newframes.append(frames[i+3])
    newframes.append(frames[i])
    newframes.append(frames[i+1])
    newframes.append(frames[i+2])
    newframes.append(frames[i+3])
w.writeframesraw(newframes)`

编辑 2: 好吧,我不知道是什么驱使我这样做,但我已经在享受它给我的自由了。我选择将wav文件复制到内存中,直接编辑副本,并将其写入输出文件。我对结果非常满意。我可以导入一个 wav,重复一次音频,然后将其写入输出文件,仅需 0.2 秒。将速度降低一半现在只需要 9 秒,而不是使用 wav 插件的旧代码需要 30 多秒 :) 这是代码,我猜仍然有点未优化,但它比原来更好。

import struct
import time as t
t.clock()
r=open(r"C:/Users/apier/Documents/LiClipse Workspace/audio editing 
software/main/aha.wav","rb")
w=open(r"C:/Users/apier/Documents/LiClipse Workspace/audio editing 
software/main/output.wav","wb")
rbuff=bytearray(r.read())
def replacebytes(array,bites,stop):
    length=len(bites)
    start=stop-length
    for i in range(start,stop):
        array[i]=bites[i-start]
def write(audio):
    w.write(audio)
def repeat(audio,repeats):
    if(repeats==1):
        return(audio)
    if(repeats==0):
        return(audio[:44])
    replacebytes(audio, struct.pack('<I', struct.unpack('<I',audio[40:44])
[0]*repeats), 44)
    return(audio+(audio[44:len(audio)-58]*(repeats-1)))
def slowhalf(audio):
    buff=bytearray()
    replacebytes(audio, struct.pack('<I', struct.unpack('<I',audio[40:44])
[0]*2), 44)
    for i in range(44,len(audio)-62,4):
        buff.append(audio[i])
        buff.append(audio[i+1])
        buff.append(audio[i+2])
        buff.append(audio[i+3])
        buff.append(audio[i])
        buff.append(audio[i+1])
        buff.append(audio[i+2])
        buff.append(audio[i+3])
    return(audio[:44]+buff)
rbuff=slowhalf(rbuff)
write(rbuff)
print(t.clock())

我很惊讶代码这么小。

readframes 返回的每个元素都是一个字节,即使类型是 int。音频样本通常为 2 个字节。通过将每个字节而不是每个整个样本加倍,您会得到噪声。

我不知道为什么一个通道会起作用,问题中显示的代码应该是 所有 噪声。

这是部分修复。它仍然混合了左右声道,但它会让你知道什么是有效的。

for i in range(0,len(frames)-1,2):
    newframes.append(frames[i])
    newframes.append(frames[i+1])
    newframes.append(frames[i])
    newframes.append(frames[i+1])

编辑:这是应该在立体声中工作的代码。它一次复制 4 个字节,左声道 2 个,右声道 2 个,然后再复制一次以将它们加倍。这将防止通道数据交错。

for i in range(0, len(frames), 4):
    for _ in range(2):
        for j in range(4):
            newframes.append(frames[i+j])