2017-10-15 32 views
0

IronPython에서 NAudio를 사용하여 여러 오디오 스트림을 믹스하여 주변 오디오를 만듭니다. 이것은 일부 트랙에서는 비교적 잘 작동하지만 다른 일부에서는 (바람, 비) 반복 재생시에 삐걱 거리는 소리가 들릴 수 있습니다.IronPython NAudio 루핑 크로스 페이드 글리치

원래 파이썬에서 LoopStream 클래스 예제를 구현하는 방법을 100 % 확신하지 못했기 때문에 10 분의 1 초 이하에 위치 확인을 간단히 시작했습니다. 나는 왜 거기에 간격이 있는지 압니다. 그 이후로, 저는 파이썬에서 LoopStream을 다시 만드는 법을 알 수 있었지만 작동했습니다.하지만 이전과 같이 여전히 갭이있었습니다. 나는 트랙의 끝 부분을 지금 같은 트랙의 시작 부분으로 크로스 페이드 (cross-fade)하려고하고 있는데, 그렇게하면 오디오가 완전히 고장 나게된다.
이 여기에 코드입니다 : 바보 같은 질문에 대한

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

잘못 ... 이미, 내가 게시 한 직후 몇 가지 문제를 발견하기 때문에 난 그냥 여기 .. ​​오류 처리 문을 추가로 사용하는 데 필요한 알았어, 그래서 자신이 1) 페이드 아웃 두 번 선언 해결 끝낼 수 있습니다 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)) 

그래서 문제가 I "가를 추가하려고이었다 내가 좋은 오류 메시지

이 줄을 가지고 한 번

그래서 해결책은 쉽게 결정되었다 결과 버퍼가 "결과가없는 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