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

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

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

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

    • This topic was modified 2 weeks, 1 day ago by Avatarkei_15.
    #1254
    Avatar鈴木啓
    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 2 weeks ago by Avatar鈴木啓.
    • This reply was modified 2 weeks ago by Avatar鈴木啓.
    • This reply was modified 2 weeks ago by Avatar鈴木啓.
    #1260
    Avatar鈴木啓
    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
    Avatar鈴木啓
    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 2 weeks ago by Avatar鈴木啓.
Viewing 5 posts - 1 through 5 (of 5 total)
  • You must be logged in to reply to this topic.