2017-10-15 20 views
0

IronPython内でNAudioを使用して、複数のオーディオストリームを混合してアンビエントオーディオを作成しています。これはいくつかのトラックではうまく動作しますが、いくつかのトラック(風、雨)の場合は、ループ再生で不快感を与えることがあります。IronPython NAudioルーピングクロスフェードグリッチ

私はLoopStreamクラスの例をPythonで実装する方法を100%確信していなかったので、10分の1秒以下で位置チェックを行うだけでした。私はなぜそこにギャップがあるのか​​知っています。それ以来、私はPythonでLoopStreamを再作成する方法を見つけ出すことができました。それはうまくいきましたが、以前と同じように再生のギャップが残っていました。私はトラックの終わりを同じトラックの始めにクロスフェードしようとしています。そのとき、オーディオが完全に不具合を起こします。ここ
はコードです:愚かな質問をして申し訳ありません

class LoopStream(WaveStream): 
    def __init__(self,WaveStream,AudioStream): 
    self.wavestream = WaveStream 
    self.audiostream = AudioStream  
    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 Read(self,buf,offset,count):  
    read = 0 
    while(read < count):    
     required = count - read 
     #print(str(self.audiostream.get_chan_id()) + " reading @ " + str(self.wavestream.Position) + "/" + str(self.wavestream.Length)) 
     pos = self.wavestream.Position 
     readthistime = self.wavestream.Read(buf,offset+read,required) 
     if pos == 0: 
     self.startbuf = buf  
     if readthistime < required: 
     self.wavestream.Position = 0 
     #print(len(buf)) 
     #buf = buf+self.startbuf    
     print(len(buf)) 
     buf = FadeOut(self,buf,offset,readthistime) + FadeIn(self,self.startbuf,0,required) 
     print(len(buf)) 
     readthistime+=required 
     print(str(self.audiostream.get_chan_id()) + " restarting1") 
     elif self.wavestream.Position + required > self.wavestream.Length:   
     #read += readthistime 
     #readthistime = self.wavestream.Read(buf,self.wavestream.Position,required) 
     #print(str(self.audiostream.get_chan_id()) + " restarting2") 
     pass 
     if self.wavestream.Position >= self.wavestream.Length: 
     self.wavestream.Position = 0 
     buf = buf + self.startbuf 
     print(str(self.audiostream.get_chan_id()) + " restarting3") 
     read += readthistime 
    return read 

    def FadeOut(self,buf,offset,count): 
    sample = 0 
    maxfadesamples = int((self.wavestream.WaveFormat.SampleRate * 75)/1000) 
    fadesamples = 0 
    while sample < count: 
     multiplier = 1.0 - (fadesamples/maxfadesamples) 
     for i in range(0,self.wavestream.WaveFormat.Channels):  
     buf[offset+sample] *= multiplier 
     sample+=1 
     fadesamples+=1 

     if fadesamples > maxfadesamples: 
     for j in range(0,self.wavestream.WaveFormat.Channels): 
      while sample < count: 
      buf[offset+sample] = 0 
      sample+=1 
    def FadeOut(self,buf,offset,count): 
    sample = 0  
    maxfadesamples = int((self.wavestream.WaveFormat.SampleRate * 75)/1000) 
    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 
+0

のErr ...まだ、私が投稿した直後にいくつかの問題に気づいたので、私はちょうどここに...エラー処理文を追加することに慣れる必要が気付いたので、私は自分が1)フェードアウトが2回宣言された解決に終わる可能性がありFadeInは実際にはまったく存在しません。 FadeOut#2をFadeInに名前を変更すると、それはまだ不具合がありましたが、無限ループに詰まっていたためです。私はそれを修正してまだ問題があるが、私はそれがどこか他の場所で読み込み機能に誤りがあると思う。 –

答えて

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つの手続きから得られた結果のバッファー "があり、私はそれらを実行してから追加する必要がありました。クロスフェードは、ギャップを著しく目立たなくします。

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