AudioStreamFromRosによるマルチチャネル録音について

HARK FORUM AudioStreamFromRosによるマルチチャネル録音について

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #1252
    kei_15
    Participant

      お世話になっております。前回の投稿の続きなのですが、AudioStreamFromRosノードを用いてマルチチャネルの音声をHARKへ送信しようと実装しております。
      1chの音声データはHARKへ送信することはできたのですが、2ch以上の音声を送信する方法が分かりません。
      この方の質問に対してhark_msgs/HarkWaveの型を記載して頂いたように、マルチチャネルのデータを送信する方法をご教授お願いいたします。

      • This topic was modified 5 years, 1 month ago by kei_15.
      #1254
      鈴木啓
      Participant

        送信する配列の値をハードコーディングしたサンプルをtest.zipとして添付いたします。
        チャンネル数は2でLengthは512、wavedataのサイズは1024としました。
        これらの値はこの方の質問にある以下の文章を参考にしております。

        length is the number of samples per frame handled by HARK. The initial value of HARK is 512 . Since HARK processed frame by frame, in other words, the size of wavedata must be nch times length=512 .

        しかしながら、これらを実行するとHARK側でSegmentation fault (core dumped)となってしまいます。
        何か間違いがあればご指摘お願い致します。

        • This reply was modified 5 years ago by 鈴木啓.
        • This reply was modified 5 years ago by 鈴木啓.
        • This reply was modified 5 years ago by 鈴木啓.
        #1260
        鈴木啓
        Participant

          度々すみません。
          srcの要素に追加すれば無事、2chの信号を送信することができました。
          失礼しました。

          #1261

          お問い合わせありがとうございます。

          こちらの投稿 を既にご覧になっているとの事でしたので、マルチチャネルの場合に必要となる情報だけ回答させて頂きます。

          hark_msgs/HarkWavench に送信するチャネル数を設定して頂き、マルチチャネルのPCMデータは wavedata が各チャネルのデータで、 src にチャネル順に格納して頂ければ送信可能です。

          Thomas氏が投稿されたソースコードをお借りするならば、

          
          result = []
          result.append(harkwaveval)
          

          の部分がマルチチャネルの場合は次のようになります。

          
          result = []
          result.append(harkwaveval_ch0)
          result.append(harkwaveval_ch1)
          result.append(harkwaveval_ch2)
          ...
          

          なお、AudioStreamFromRosノードでは下記のように実装しております。C/C++をよく書かれている方でしたら下記のソースコードの方が分かりやすいかもしれません。

          
          for (int k = 0; k < nb_channels; k++) {
            for (int i = 0; i < length; i++) {
              (*output)(k, i) = cbf->deque_wave[0].src[k].wavedata[i];
            }
          }
          

          https://www.hark.jp/download/source-code/
          上記URLでHARKの全ソースコードを公開しておりますので、その他の部分についても実装内容を確認する事が可能です。

          ———-

          data_bytes の件、書き忘れました。全チャネル分になりますのでご注意ください。

          以上、ご参考になれば幸いです。

          #1263
          鈴木啓
          Participant

            ありがとうございます。
            無事TAMAGOで録音した8chの音声をROSを用いて送信することができました。
            自分と同じような人が困らないよう、ここに自分のサンプルファイルを示しておきます。
            このサンプルでは同じ階層に存在するinputというディレクトリの中のwavファイルを、全てROSへと送信します。

            
            #!/usr/bin/env python
            ## coding: UTF-8
            import pyaudio
            import wave
            import rospy
            import numpy as np
            import os
            from hark_msgs.msg import HarkWave, HarkWaveVal
            
            class MultiWav:
                def __init__(self):
                    np.set_printoptions(threshold=0)
                    self._wav_data_pub = rospy.Publisher('wavdata_py', HarkWave, queue_size=10)
                    self.CHUNK = 512
                    self.multi_msgs = []
                    self.p = pyaudio.PyAudio()
                    print("-=" * 35)
                    self.count = 0
            
                    self.here_path = os.path.dirname(__file__)
                    if self.here_path == "":
                        self.here_path = "."
            
                def initialize_HarkWave(self):
                    self.hw = HarkWave()
                    self.hwv = HarkWaveVal()
                    self.sent_flag = False
                    self.hw.length = 512
                    self.hw.nch = self.ch
                    self.hw.data_bytes = self.hw.length * self.hw.nch * 4
            
                def read_input_dir(self, path):
                    inputs = os.listdir(path)
                    wf_list = []
                    for input in inputs:
                        input_path = path + "/" + input
                        wf = wave.open(input_path, 'rb')
                        wf_list.append(wf)
                    # 他のメソッドで使用するメンバ変数等を定義
                    self.channel0_path = path + "/" + inputs[0]
                    self.ch = len(inputs)
                    return wf_list
            
                def wav2array(self, wfs):
                    for wf in wfs:
                        data = wf.readframes(self.CHUNK)
                        msgs_nest = []
                        while data != '':
                            # stream.write(data)
                            data = wf.readframes(self.CHUNK)
                            wavdata = np.fromstring(data, "Int16").tolist()
                            if len(wavdata) == 0:
                                break
                            msgs_nest.append(wavdata)
                        self.multi_msgs.append(msgs_nest)
            
                def generate_senddata_with_playing(self, multi_msgs):
                    wf0 = wave.open(self.channel0_path, 'rb')
                    stream = self.p.open(
                        format=self.p.get_format_from_width(wf0.getsampwidth()),
                        channels=wf0.getnchannels(),
                        rate=wf0.getframerate(),
                        output=True
                    )
                    data = wf0.readframes(self.CHUNK)
            
                    while data != '':
                        stream.write(data)
                        data = wf0.readframes(self.CHUNK)
                        wavdata = np.fromstring(data, "Int16")
                        print("playing this now: " + str(wavdata))
                        if len(wavdata) == 0:
                            break
                        multi_msg_1d = []
                        for mono_msgs in multi_msgs:
                            multi_msg_1d.extend(mono_msgs[self.count])
                        self.send(multi_msg_1d)
                        self.count = self.count + 1
                    stream.close()
                    self.p.terminate()
            
                def send(self, array):
                    hw = self.hw
                    hwv = self.hwv
                    hw.header.stamp = rospy.Time.now()
                    hw.header.frame_id = str(self.count)
                    hw.count = self.count
                    hw.src = []
                    for i in range(hw.nch):
                        start_index = i * hw.length
                        end_index = start_index + hw.length
                        mono_arr = array[start_index:end_index]
                        hwv.wavedata = mono_arr
                        hw.src.append(hwv)
                    self._wav_data_pub.publish(hw)
            
            if __name__ == '__main__':
                rospy.init_node('wav_reader_py',anonymous=True)
                mw = MultiWav()
                wavfiles = mw.read_input_dir(mw.here_path + "/input")
                mw.initialize_HarkWave()
                mw.wav2array(wavfiles)
                mw.generate_senddata_with_playing(mw.multi_msgs)
            
            • This reply was modified 5 years ago by 鈴木啓.
          Viewing 5 posts - 1 through 5 (of 5 total)
          • You must be logged in to reply to this topic.