我在IronPython中使用NAudio来混合多个音频流来创建环境音频。这对于某些音轨来说效果相当不错,但对于其他音轨(风,雨),它可以在循环播放时产生震动停止/开始。
因为我不是100%确定如何在python中实现LoopStream类示例,所以我开始只是在十分之一秒或更短的时间后进行位置检查。我知道为什么我在那里有差距。从那以后,我能够弄清楚如何在python中重新创建LoopStream,并且它可以工作,但我仍然像以前一样在播放方面存在差距。我现在试图将轨道的末端交叉淡入到同一轨道的开头,当我这样做时,音频完全出现故障。
这是代码:
rawdata1$usage5 <- cut(rawdata1$Usage_Percentage,
breaks = quantile(rawdata1$Usage_Percentage),
include.lowest=T,labels=F)
答案 0 :(得分:0)
很抱歉提出愚蠢的问题....应该很明显我正在使用的函数没有返回缓冲区,而只是在传递给它们的缓冲区上。
一旦我收到一条好的错误消息,就很容易确定解决方案
这一行:
buf = FadeOut(self,buf,offset,readthistime) + FadeIn(self,self.startbuf,0,required)
变成了:
try:
self.FadeOut(buf,offset,readthistime)
self.FadeIn(self.startbuf,0,required)
buf = buf = self.startbuf
except Exception, e:
print(repr(e))
所以问题是我试图从2个没有结果的程序中添加“结果缓冲区”,我只需要运行它们然后进行添加。交叉淡入淡出使得差距显着减少。
答案 1 :(得分:0)
下面是一个比我之前的尝试更好的解决方案,这个解决方案是交叉渐变而不是淡入/淡出,这确实最小化了间隙但是在某些音轨重启时仍然是一个明显的故障。
class LoopStream(WaveStream):
def __init__(self,WaveStream,AudioStream):
self.wavestream = WaveStream
self.originalstream = self.wavestream
self.audiostream = AudioStream
if (float(self.get_Length()) / self.WaveFormat.AverageBytesPerSecond) > 6:
self.CFSeconds = 3.1
else:
#self.CFSeconds = (self.LSeconds / 2.0) + 0.1
self.CFSeconds = ((float(self.get_Length()) / self.WaveFormat.AverageBytesPerSecond)/2) - 0.1
self.CFBytes = int(round(self.WaveFormat.AverageBytesPerSecond*self.CFSeconds))
#determine bytes per section of audio
temp = (self.WaveFormat.BitsPerSample / 8) * self.WaveFormat.Channels
#determine how many bytes we are over target
temp = self.CFBytes % temp
#subtract bits to get to target
self.CFBytes-=temp
self.startbuf = Array.CreateInstance(System.Byte,self.CFBytes)
self.endbuf = Array.CreateInstance(System.Byte,self.CFBytes)
self.wavestream.Read(self.startbuf,0,self.CFBytes)
self.wavestream.Position = self.Length - self.CFBytes
self.wavestream.Read(self.endbuf,0,self.CFBytes)
self.wavestream.Position = 0
#self.startbuf = self.buf[:int(round(self.WaveFormat.AverageBytesPerSecond*CFSeconds))]
self.FadeIn(self.startbuf,0,int(round(self.WaveFormat.AverageBytesPerSecond*self.CFSeconds)))
#self.endbuf = self.buf[self.Length-int(round(self.WaveFormat.AverageBytesPerSecond*CFSeconds)):]
self.FadeOut(self.endbuf,0,int(round(self.WaveFormat.AverageBytesPerSecond*self.CFSeconds)))
self.FirstPlay = True
self.startstream = RawSourceWaveStream(self.startbuf,0,self.CFBytes,self.WaveFormat)
self.endstream = RawSourceWaveStream(self.endbuf,0,self.CFBytes,self.WaveFormat)
self.crossfadestream = MixingWaveProvider32() #self.startstream,self.endstream)
self.crossposition = 0
self.crossfadestream.AddInputStream(self.startstream)
self.crossfadestream.AddInputStream(self.endstream)
self.CFBuffer = Array.CreateInstance(System.Byte,self.CFBytes)
self.crossfadestream.Read(self.CFBuffer,0,self.CFBytes)
print(self.audiostream.chan_id,"initialized")
def get_WaveFormat(self):
return self.wavestream.WaveFormat
def get_Length(self):
return self.wavestream.Length
def get_Position(self):
return self.wavestream.Position
def HasData(count):
return True
def LSeconds(self):
return float(self.get_Length()) / self.WaveFormat.AverageBytesPerSecond
def PSeconds(self):
return float(self.get_Position()) / self.WaveFormat.AverageBytesPerSecond
def Read(self,buf,offset,count):
read = 0
while(read < count):
required = count - read
readthistime = 0
if self.FirstPlay == True:
if (int(self.Position) + read >= self.CFBytes) or (int(self.Position) + read >= int(self.Length) - self.CFBytes):
self.FirstPlay = False
if self.FirstPlay == True or ((int(self.Position) + read) < (int(self.Length) - self.CFBytes) and (int(self.Position) + read > self.CFBytes)):
try:
#print(self.audiostream.chan_id,"Normal")
readthistime = self.wavestream.Read(buf,offset+read,required)
except Exception, e:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type,fname,exc_tb.tb_lineno)
else:
try:
#print(self.audiostream.chan_id,"Crossfade")
buf = self.CFBuffer
self.wavestream.Position = self.CFBytes + ((self.WaveFormat.BitsPerSample/8)*self.WaveFormat.Channels)
read += self.CFBytes
return read
except Exception, e:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type,fname,exc_tb.tb_lineno)
read += readthistime
return read
def FadeOut(self,buf,offset,count):
sample = 0
maxfadesamples = int((self.WaveFormat.SampleRate * self.CFSeconds))
fadesamples = 0
while sample < count:
multiplier = 1.0 - (fadesamples / maxfadesamples)
for i in range(0,self.wavestream.WaveFormat.Channels):
try:
buf[offset+sample] *= multiplier
except Exception, e:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(sample,exc_type,fname,exc_tb.tb_lineno)
return
sample+=1
fadesamples+=1
if fadesamples > maxfadesamples:
while sample < count:
buf[offset+sample] = 0
sample+=1
break
def FadeIn(self,buf,offset,count):
sample = 0
maxfadesamples = int((self.WaveFormat.SampleRate * self.CFSeconds))
fadesamples = 0
while sample < count:
multiplier = (fadesamples / maxfadesamples)
for i in range(0,self.wavestream.WaveFormat.Channels):
buf[offset+sample] *= multiplier
sample+=1
fadesamples+=1
if fadesamples>maxfadesamples:
break