繁体   English   中英

断断续续的音频从分离然后加入.wav立体声通道

[英]Choppy audio from separating and then joining .wav stereo channels

我目前正在使用python处理.wav文件,使用Pyaudio传输音频,并使用python wave库加载文件数据。 我计划稍后再处理各个立体声通道,包括信号幅度和声像平移,但现在我只是试图分离波形文件的两个通道,并将它们缝合起来在一起-希望最终得到与输入数据相同的数据。

下面是我的代码。 方法getRawSample可以正常工作,并且我可以通过该函数流式传输音频。 问题是我的getSample方法。 沿线路的某个位置,我将音频的两个通道分开,然后将它们重新连接在一起,音频会失真。 我什至已经注释掉了我进行幅度和声像调整的部分,因此从理论上讲,它是数据输入->数据输出。
以下是我的代码示例:

class Sample(threading.Thread) :

def __init__(self, filepath, chunk):
    super(Sample, self).__init__()
    self.CHUNK = chunk
    self.filepath = filepath
    self.wave = wave.open(self.filepath, 'rb')
    self.amp = 0.5 # varies from 0 to 1
    self.pan = 0 # varies from -pi to pi
    self.WIDTH = self.wave.getsampwidth()
    self.CHANNELS  = self.wave.getnchannels()
    self.RATE = self.wave.getframerate()
    self.MAXFRAMEFEEDS = self.wave.getnframes()/self.CHUNK  # maximum even number of chunks
    self.unpstr = '<{0}h'.format(self.CHUNK*self.WIDTH)  # format for unpacking the sample byte string
    self.pckstr = '<{0}h'.format(self.CHUNK*self.WIDTH)  # format for unpacking the sample byte string

    self.framePos = 0  # keeps track of how many chunks of data fed

#  panning and amplitude adjustment of input sample data

def panAmp(self, data, panVal, ampVal):  # when panning, using constant power panning
    [left, right] = self.getChannels(data)
    #left = np.multiply(0.5, left) #(np.sqrt(2)/2)*(np.cos(panVal) + np.sin(panVal))
    #right = np.multiply(0.5, right)  # (np.sqrt(2)/2)*(np.cos(panVal) - np.sin(panVal))
    outputList = self.combineChannels(left, right)
    dataResult = struct.pack(self.pckstr, *outputList)
    return dataResult

def getChannels(self, data):
    dataPrepare = list(struct.unpack(self.unpstr, data))
    left = dataPrepare[0::self.CHANNELS]
    right = dataPrepare[1::self.CHANNELS]
    return [left, right]

def combineChannels(self, left, right):
    stereoData = left
    for i in range(0, self.CHUNK/self.WIDTH):
        index = i*2+1
        stereoData = np.insert(stereoData, index, right[i*self.WIDTH:(i+1)*self.WIDTH])
    return stereoData

def getSample(self, panVal, ampVal):
    data = self.wave.readframes(self.CHUNK)
    self.framePos += 1
    if self.framePos > self.MAXFRAMEFEEDS:  # if no more audio samples to process
        self.wave.rewind()
        data = self.wave.readframes(self.CHUNK)
        self.framePos = 1
    return self.panAmp(data, panVal, ampVal)

def getRawSample(self):  # for debugging, bypasses pan and amp functions
    data = self.wave.readframes(self.CHUNK)
    self.framePos += 1
    if self.framePos > self.MAXFRAMEFEEDS:  # if no more audio samples to process
        self.wave.rewind()
        data = self.wave.readframes(self.CHUNK)
        self.framePos = 1
    return data

我怀疑该错误是我将左右声道缝合在一起的方式,但不确定。 我使用16位44100khz .wav文件加载该项目。 以下是音频文件的链接,以便您可以听到生成的音频输出。 第一部分通过getSample方法运行两个文件(两个通道),而下一部分通过getRawSample方法运行相同的文件。

https://dl.dropboxusercontent.com/u/24215404/pythonaudiosample.wav

如前所述,基于音频,立体声文件似乎失真了。 查看上面文件的波形,经过getSample方法后,左右声道似乎完全相同。

如果需要,我还可以发布包括主要功能在内的代码。 希望我的问题不是很模糊,但是我非常感谢您的帮助或投入!

因为它经常发生,所以我睡着了,第二天醒来就提出了解决方案。
问题出在CombineChannels函数中。 以下是工作代码:

   def combineChannels(self, left, right):
    stereoData = left
    for i in range(0, self.CHUNK):
        index = i*2+1
        stereoData = np.insert(stereoData, index, right[i:(i+1)])
    return stereoData

的变化是

  • 对于循环边界:我有1024项(同我的块大小)的左侧右侧的列表中,我ofcourse需要通过这些中的每一个迭代。
  • index:索引定义保持不变
  • stereodata:再次,在这里我记得我正在处理列表,每个列表包含一个音频帧。 问题中的代码假定我的列表存储为字节串,但是事实并非如此。 如您所见,生成的代码要简单得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM