我的程序将音乐速度降低了 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])
我正在使用 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])