Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在数据流中查找一系列模式_Python_Algorithm_Audio_Stream - Fatal编程技术网

Python 在数据流中查找一系列模式

Python 在数据流中查找一系列模式,python,algorithm,audio,stream,Python,Algorithm,Audio,Stream,(这是用Python编写的,代码会很棒,但我主要对算法感兴趣。) 我正在监视一个音频流(PyAudio)并寻找一系列5个POP(见底部的可视化)。我正在对流进行读取()并获取刚刚读取的块的RMS值(类似于)。我的问题是,我不是在寻找一个单一的事件,而是一系列事件(pop),它们具有一些特征,但不像我希望的那么布尔。检测这五种持久性有机污染物最直接(最有效)的方法是什么 RMS函数为我提供了如下流: 0.000580998485254, 0.00045098391298, 0.0075143644

(这是用Python编写的,代码会很棒,但我主要对算法感兴趣。)

我正在监视一个音频流(PyAudio)并寻找一系列5个POP(见底部的可视化)。我正在对流进行读取()并获取刚刚读取的块的RMS值(类似于)。我的问题是,我不是在寻找一个单一的事件,而是一系列事件(pop),它们具有一些特征,但不像我希望的那么布尔。检测这五种持久性有机污染物最直接(最有效)的方法是什么

RMS函数为我提供了如下流:

0.000580998485254, 0.00045098391298, 0.00751436443973, 0.002733730043, 0.00160775708652, 0.000847808804511
如果我为您搜索(类似的流),它看起来会更有用:

你可以在第3项中看到弹出,大概是在第4项中它安静下来的时候,也许尾端是在第5项的一小部分

我想连续检测其中的5个

我天真的做法是: a) 定义pop是什么:块的RMS超过.002。至少2个区块,但不超过4个区块。以沉默开始,以沉默结束

此外,我很想定义什么是沉默(忽略不太响亮但不太沉默的块,但我不确定这比将“pop”视为布尔值更有意义)

b) 然后有一个状态机,它跟踪一组变量,并有一组if语句。比如:

while True:
  is_pop = isRMSAmplitudeLoudEnoughToBeAPop(stream.read())

  if is_pop:
    if state == 'pop':
      #continuation of a pop (or maybe this continuation means
      #that it's too long to be a pop
      if num_pop_blocks <= MAX_POP_RECORDS:
        num_pop_blocks += 1
      else:
        # too long to be a pop
        state = 'waiting'
        num_sequential_pops = 0
    else if state == 'silence':
      #possible beginning of a pop
      state = 'pop'
      num_pop_blocks += 1
      num_silence_blocks = 0
  else:
    #silence
    if state = 'pop':
      #we just transitioned from pop to silence
      num_sequential_pops += 1

      if num_sequential_pops == 5:
        # we did it
        state = 'waiting'
        num_sequential_pops = 0
        num_silence_blocks = 0

        fivePopsCallback()
    else if state = 'silence':
      if num_silence_blocks >= MAX_SILENCE_BLOCKS:
        #now we're just waiting
        state = 'waiting'
        num_silence_blocks = 0
        num_sequential_pops = 0
为True时:
is_pop=isrmSamplicationNoughtObeapop(stream.read())
如果是流行音乐:
如果state==“pop”:
#流行音乐的延续(或者这个延续意味着
#它太长了,不能成为流行音乐
如果num_pop_blocks=MAX_SILENCE_blocks:
#现在我们只是在等待
状态='等待'
num_silence_blocks=0
num_sequential_pops=0
这段代码一点也不完整(可能有一两个bug),但说明了我的思路。它肯定比我希望的要复杂,这就是我征求建议的原因


您可能需要计算最后p个点的值,其中p~=4,并将结果与原始输入数据一起绘制

然后,你可以使用平滑平均值的最大值作为一个pop。定义一个最大间隔,在该间隔内可以看到五个pop,这可能是你的目标

调整p以获得最佳拟合


如果还没有Python模块,我不会感到惊讶,但我还没有看过。

在我看来,这是一种幼稚的方法,有一个正在进行的循环和一些变量需要维护并转换到新状态。不过,在完成之后,我想到,我应该探索hotword检测,因为5 conse可爱的点击基本上是一个热门词。它们有一个模式,我必须寻找

无论如何,这是我的代码:

POP_MIN_MS = 50
POP_MAX_MS = 150

POP_GAP_MIN_MS = 50
POP_GAP_MAX_MS = 200

POP_BORDER_MIN_MS = 500

assert POP_BORDER_MIN_MS > POP_GAP_MAX_MS

POP_RMS_THRESHOLD_MIN = 100

FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100 # Sampling Rate -- frames per second
INPUT_BLOCK_TIME_MS = 50
INPUT_FRAMES_PER_BLOCK = int(RATE*INPUT_BLOCK_TIME_MS/1000)

POP_MIN_BLOCKS = POP_MIN_MS / INPUT_BLOCK_TIME_MS
POP_MAX_BLOCKS = POP_MAX_MS / INPUT_BLOCK_TIME_MS

POP_GAP_MIN_BLOCKS = POP_GAP_MIN_MS / INPUT_BLOCK_TIME_MS
POP_GAP_MAX_BLOCKS = POP_GAP_MAX_MS / INPUT_BLOCK_TIME_MS

POP_BORDER_MIN_BLOCKS = POP_BORDER_MIN_MS / INPUT_BLOCK_TIME_MS


def listen(self):
    pops = 0
    sequential_loud_blocks = 0
    sequential_notloud_blocks = 0

    stream = self.pa.open(
      format=FORMAT,
      channels=CHANNELS,
      rate=RATE,
      input=True,
      frames_per_buffer=INPUT_FRAMES_PER_BLOCK
    )

    states = {
      'PENDING': 1,
      'POPPING': 2,
      'ENDING': 3,
    }

    state = states['PENDING']

    while True:
      amp = audioop.rms(stream.read(INPUT_FRAMES_PER_BLOCK), 2)

      is_loud = (amp >= POP_RMS_THRESHOLD_MIN)

      if state == states['PENDING']:
        if is_loud:
          # Only switch to POPPING if it's been quiet for at least the border
          #   period. Otherwise stay in PENDING.
          if sequential_notloud_blocks >= POP_BORDER_MIN_BLOCKS:
            state = states['POPPING']
            sequential_loud_blocks = 1

          # If it's now loud then reset the # of notloud blocks
          sequential_notloud_blocks = 0
        else:
          sequential_notloud_blocks += 1

      elif state == states['POPPING']:

        if is_loud:
          sequential_loud_blocks += 1
          # TODO: Is this necessary?
          sequential_notloud_blocks = 0

          if sequential_loud_blocks > POP_MAX_BLOCKS:
            # it's been loud for too long; this isn't a pop
            state = states['PENDING']
            pops = 0
            #print "loud too long"
            # since it has been loud and remains loud then no reason to reset
            #   the notloud_blocks count

        else:
          # not loud
          if sequential_loud_blocks:
            # just transitioned from loud. was that a pop?
            # we know it wasn't too long, or we would have transitioned to
            #   PENDING during the pop
            if sequential_loud_blocks < POP_MIN_BLOCKS:
              # wasn't long enough
              # go to PENDING
              state = states['PENDING']
              pops = 0
              #print "not loud long enough"
            else:
              # just right
              pops += 1
              logging.debug("POP #%s", pops)

            sequential_loud_blocks = 0
            sequential_notloud_blocks += 1

          else:
            # it has been quiet. and it's still quiet
            sequential_notloud_blocks += 1

            if sequential_notloud_blocks > POP_GAP_MAX_BLOCKS:
              # it was quiet for too long
              # we're no longer popping, but we don't know if this is the
              #   border at the end
              state = states['ENDING']

      elif state == states['ENDING']:
        if is_loud:
          # a loud block before the required border gap. reset
          # since there wasn't a gap, this couldn't be a valid pop anyways
          #   so just go back to PENDING and let it monitor for the border
          sequential_loud_blocks = 1
          sequential_notloud_blocks = 0
          pops = 0

          state = states['PENDING']
        else:
          sequential_notloud_blocks += 1

          # Is the border time (500 ms right now) enough of a delay?
          if sequential_notloud_blocks >= POP_BORDER_MIN_BLOCKS:
            # that's a bingo!
            if pops == 5:

              stream.stop_stream()

              # assume that starting now the channel is not silent
              start_time = time.time()


              print ">>>>> 5 POPS"

              elapsed = time.time() - start_time

              #time.time() may return fractions of a second, which is ideal    
              stream.start_stream()

              # do whateve we need to do

            state = states['PENDING']
            pops = 0
POP_MIN_MS=50
POP_MAX_MS=150
POP_GAP_MIN_MS=50
波普_间隙_最大值_MS=200
POP_BORDER_MIN_MS=500
断言POP_BORDER_MIN_MS>POP_GAP_MAX_MS
POP\u RMS\u阈值\u最小值=100
格式=pyaudio.paInt16
通道=2
速率=44100#采样速率--每秒帧数
输入\块\时间\毫秒=50
每块输入帧=int(速率*输入块时间=MS/1000)
POP_MIN_BLOCKS=POP_MIN_MS/输入_BLOCK_TIME_MS
POP_MAX_BLOCKS=POP_MAX_MS/输入_BLOCK_TIME_MS
POP_GAP_MIN_BLOCKS=POP_GAP_MIN_MS/输入_BLOCK_TIME_MS
POP_GAP_MAX_BLOCKS=POP_GAP_MAX_MS/输入_BLOCK_TIME_MS
POP_BORDER_MIN_BLOCKS=POP_BORDER_MIN_MS/输入_BLOCK_TIME_MS
def监听(self):
pops=0
顺序块=0
顺序块=0
流=self.pa.open(
格式=格式,
频道=频道,
比率=比率,
输入=真,
每个缓冲区的帧数=每个块的输入帧数
)
国家={
“待定”:1,
"砰砰":2,,
"结局":3,,
}
状态=状态['PENDING']
尽管如此:
amp=audioop.rms(流读(每个块输入帧),2)
是否响亮=(amp>=砰砰声\u RMS\u阈值\u MIN)
如果state==states['PENDING']:
如果声音很大:
#只有在至少在边境保持安静的情况下才切换到弹出
#期间。否则待决。
如果连续的\u notloud\u块>=POP\u BORDER\u MIN\u块:
状态=状态['POPPING']
顺序块=1
#如果现在是响亮的,则重置notloud块的#
顺序块=0
其他:
顺序块+=1
elif state==状态['POPPING']:
如果声音很大:
顺序块+=1
#托多:这有必要吗?
顺序块=0
如果顺序块>弹出块>最大块:
#声音太大太久了,这不是流行音乐
状态=状态['PENDING']
pops=0
#打印“太长”
#因为它一直很响并且一直很响,所以没有理由重置
#notloud_积木计数
其他:
#不大声
如果连续_loud_块:
#刚从大声转换过来,那是流行音乐吗?
#我们知道时间不会太长,否则我们会过渡到
#在pop期间挂起
如果连续的\u loud\u块弹出块>最大块:
#安静了太久
#我们不再蹦蹦跳跳了,但我们不知道这是不是
#尽头的边界
状态=状态[“结束”]
elif state==状态['ENDING']:
如果是_
POP_MIN_MS = 50
POP_MAX_MS = 150

POP_GAP_MIN_MS = 50
POP_GAP_MAX_MS = 200

POP_BORDER_MIN_MS = 500

assert POP_BORDER_MIN_MS > POP_GAP_MAX_MS

POP_RMS_THRESHOLD_MIN = 100

FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100 # Sampling Rate -- frames per second
INPUT_BLOCK_TIME_MS = 50
INPUT_FRAMES_PER_BLOCK = int(RATE*INPUT_BLOCK_TIME_MS/1000)

POP_MIN_BLOCKS = POP_MIN_MS / INPUT_BLOCK_TIME_MS
POP_MAX_BLOCKS = POP_MAX_MS / INPUT_BLOCK_TIME_MS

POP_GAP_MIN_BLOCKS = POP_GAP_MIN_MS / INPUT_BLOCK_TIME_MS
POP_GAP_MAX_BLOCKS = POP_GAP_MAX_MS / INPUT_BLOCK_TIME_MS

POP_BORDER_MIN_BLOCKS = POP_BORDER_MIN_MS / INPUT_BLOCK_TIME_MS


def listen(self):
    pops = 0
    sequential_loud_blocks = 0
    sequential_notloud_blocks = 0

    stream = self.pa.open(
      format=FORMAT,
      channels=CHANNELS,
      rate=RATE,
      input=True,
      frames_per_buffer=INPUT_FRAMES_PER_BLOCK
    )

    states = {
      'PENDING': 1,
      'POPPING': 2,
      'ENDING': 3,
    }

    state = states['PENDING']

    while True:
      amp = audioop.rms(stream.read(INPUT_FRAMES_PER_BLOCK), 2)

      is_loud = (amp >= POP_RMS_THRESHOLD_MIN)

      if state == states['PENDING']:
        if is_loud:
          # Only switch to POPPING if it's been quiet for at least the border
          #   period. Otherwise stay in PENDING.
          if sequential_notloud_blocks >= POP_BORDER_MIN_BLOCKS:
            state = states['POPPING']
            sequential_loud_blocks = 1

          # If it's now loud then reset the # of notloud blocks
          sequential_notloud_blocks = 0
        else:
          sequential_notloud_blocks += 1

      elif state == states['POPPING']:

        if is_loud:
          sequential_loud_blocks += 1
          # TODO: Is this necessary?
          sequential_notloud_blocks = 0

          if sequential_loud_blocks > POP_MAX_BLOCKS:
            # it's been loud for too long; this isn't a pop
            state = states['PENDING']
            pops = 0
            #print "loud too long"
            # since it has been loud and remains loud then no reason to reset
            #   the notloud_blocks count

        else:
          # not loud
          if sequential_loud_blocks:
            # just transitioned from loud. was that a pop?
            # we know it wasn't too long, or we would have transitioned to
            #   PENDING during the pop
            if sequential_loud_blocks < POP_MIN_BLOCKS:
              # wasn't long enough
              # go to PENDING
              state = states['PENDING']
              pops = 0
              #print "not loud long enough"
            else:
              # just right
              pops += 1
              logging.debug("POP #%s", pops)

            sequential_loud_blocks = 0
            sequential_notloud_blocks += 1

          else:
            # it has been quiet. and it's still quiet
            sequential_notloud_blocks += 1

            if sequential_notloud_blocks > POP_GAP_MAX_BLOCKS:
              # it was quiet for too long
              # we're no longer popping, but we don't know if this is the
              #   border at the end
              state = states['ENDING']

      elif state == states['ENDING']:
        if is_loud:
          # a loud block before the required border gap. reset
          # since there wasn't a gap, this couldn't be a valid pop anyways
          #   so just go back to PENDING and let it monitor for the border
          sequential_loud_blocks = 1
          sequential_notloud_blocks = 0
          pops = 0

          state = states['PENDING']
        else:
          sequential_notloud_blocks += 1

          # Is the border time (500 ms right now) enough of a delay?
          if sequential_notloud_blocks >= POP_BORDER_MIN_BLOCKS:
            # that's a bingo!
            if pops == 5:

              stream.stop_stream()

              # assume that starting now the channel is not silent
              start_time = time.time()


              print ">>>>> 5 POPS"

              elapsed = time.time() - start_time

              #time.time() may return fractions of a second, which is ideal    
              stream.start_stream()

              # do whateve we need to do

            state = states['PENDING']
            pops = 0