Example #1
0
    def test_create(self):
        try:
            opuslib.Encoder(1000, 3, opuslib.APPLICATION_AUDIO)
        except opuslib.OpusError as ex:
            self.assertEqual(ex.code, opuslib.BAD_ARG)

        opuslib.Encoder(48000, 2, opuslib.APPLICATION_AUDIO)
Example #2
0
    def startout(self):
        self._loopthread = True
        self._enc = opuslib.Encoder(self.RATE, self.CHANNELS,
                                    opuslib.APPLICATION_AUDIO)
        self._dec = opuslib.Decoder(self.RATE, self.CHANNELS)
        self._enc.complexity = self._opuscomplexity
        self._enc.bitrate = self._opusbitrate
        self.__runstreamin()
        self.__runstreamout()

        if self._mode == "sender":
            self._socketout.bind(
                (self._sendingPeer_ip, self._sendingPeer_port))
            d = threading.Thread(target=self.__sendpacks, args=())
            d.setDaemon(True)
            d.start()
        if self._mode == "receiver":
            self._socketin.bind(
                (self._receivingPeer_ip, self._receivingPeer_port))
            r = threading.Thread(target=self.__getpacks, args=())
            r.setDaemon(True)
            r.start()
        if self._mode == "loop":
            self._socketout.bind(
                (self._sendingPeer_ip, self._sendingPeer_port))
            self._socketin.bind(
                (self._receivingPeer_ip, self._receivingPeer_port))
            d = threading.Thread(target=self.__sendpacks, args=())
            d.setDaemon(True)
            d.start()
            r = threading.Thread(target=self.__getpacks, args=())
            r.setDaemon(True)
            r.start()

        atexit.register(self.__close)
Example #3
0
 def __init__(self):
     self.enc = opuslib.Encoder(24000, 1, opuslib.APPLICATION_RESTRICTED_LOWDELAY)
     self.enc.bitrate = 64000
     self.enc.lsb_depth = 16
     self.enc.packet_loss_perc = 25
     self.enc.signal = opuslib.SIGNAL_MUSIC
     self.listeners = []
def handle_post(userid,
                n_samples,
                in_data_raw,
                new_events,
                query_string,
                print_status=True) -> Tuple[Any, str]:
    try:
        enc, dec = users[userid]
    except KeyError:
        enc = opuslib.Encoder(server.SAMPLE_RATE, CHANNELS,
                              opuslib.APPLICATION_AUDIO)
        dec = opuslib.Decoder(server.SAMPLE_RATE, CHANNELS)
        users[userid] = enc, dec

    in_data = np.frombuffer(in_data_raw, dtype=np.uint8)

    # If the user does not send us any data, we will treat it as silence of length n_samples. This is useful if they are just starting up.
    if len(in_data) == 0:
        if n_samples == 0:
            raise ValueError("Must provide either n_samples or data")
        in_data = np.zeros(n_samples, np.float32)
    else:
        packets = unpack_multi(in_data)
        decoded = []
        for p in packets:
            d = dec.decode_float(p.tobytes(),
                                 OPUS_FRAME_SAMPLES,
                                 decode_fec=False)
            decoded.append(np.frombuffer(d, np.float32))
        in_data = np.concatenate(decoded)

    # Sending n_samples is optional if data is sent, but in case of both they must match
    if n_samples == 0:
        n_samples = len(in_data)
    if n_samples != len(in_data):
        raise ValueError(
            "Client is confused about how many samples it sent (got %s expected %s"
            % (n_samples, len(in_data)))

    if shared_memory is not None:
        data, x_audio_metadata = handle_json_post(in_data, new_events,
                                                  query_string, print_status)
    else:
        data, x_audio_metadata = server.handle_post(in_data, new_events,
                                                    query_string, print_status)

    packets = data.reshape([-1, OPUS_FRAME_SAMPLES])
    encoded = []
    for p in packets:
        e = np.frombuffer(enc.encode_float(p.tobytes(), OPUS_FRAME_SAMPLES),
                          np.uint8)
        encoded.append(e)
    data = pack_multi(encoded).tobytes()

    return data, x_audio_metadata
Example #5
0
    def create_encoder(self):
        """create the encoder instance, and set related constants"""
        if not self.codec:
            return ()

        if self.codec.opus:
            self.encoder = opuslib.Encoder(PYMUMBLE_SAMPLERATE, 1, 'voip')
            self.encoder_framesize = self.audio_per_packet
            self.codec_type = PYMUMBLE_AUDIO_TYPE_OPUS
        else:
            raise CodecNotSupportedError('')

        self._set_bandwidth()
    def __init__(
        self, source: str, volume=0.5, guild_id: int = 0, *args, **kwargs
    ):
        self.volume = volume
        super().__init__(source, *args, **kwargs)
        self.guild_id = guild_id
        self.bytes_read = 0

        self.decoder = opuslib.Decoder(
            OpusEncoder.SAMPLING_RATE, OpusEncoder.CHANNELS
        )
        self.encoder = opuslib.Encoder(
            OpusEncoder.SAMPLING_RATE, OpusEncoder.CHANNELS, "voip"
        )
Example #7
0
def write_opus(opus_file, audio_format, audio_data):
    rate, channels, width = audio_format
    frame_size = get_opus_frame_size(rate)
    import opuslib  # pylint: disable=import-outside-toplevel
    encoder = opuslib.Encoder(rate, channels, 'audio')
    chunk_size = frame_size * channels * width
    opus_file.write(pack_number(len(audio_data), OPUS_PCM_LEN_SIZE))
    opus_file.write(pack_number(rate, OPUS_RATE_SIZE))
    opus_file.write(pack_number(channels, OPUS_CHANNELS_SIZE))
    opus_file.write(pack_number(width, OPUS_WIDTH_SIZE))
    for i in range(0, len(audio_data), chunk_size):
        chunk = audio_data[i:i + chunk_size]
        # Preventing non-deterministic encoding results from uninitialized remainder of the encoder buffer
        if len(chunk) < chunk_size:
            chunk = chunk + bytearray(chunk_size - len(chunk))
        encoded = encoder.encode(chunk, frame_size)
        opus_file.write(pack_number(len(encoded), OPUS_CHUNK_LEN_SIZE))
        opus_file.write(encoded)
Example #8
0
    def __init__(self, remote_host_address, remote_host_port, host_address,
                 rtp_port):
        self.CHUNK_SIZE = 960  #640 #320
        self.mic = MicDevice(sr=self.SAMPLE_RATE, chunk_size=self.CHUNK_SIZE)

        self.sender = RTPSendClient(remote_host_address=remote_host_address,
                                    remote_host_port=remote_host_port)

        self.receiver = RTPReceiveClient(host_address=host_address,
                                         rtp_port=rtp_port)
        self.opus_encode = opuslib.Encoder(self.SAMPLE_RATE, 1,
                                           opuslib.APPLICATION_VOIP)
        self.opus_decode = opuslib.Decoder(self.SAMPLE_RATE, 1)

        self.aout = AudioOutput()
        self.frame_count = 0
        self.start_ts = -1.0
        print('init client')
Example #9
0
def write_opus(opus_file, audio_data, audio_format=DEFAULT_FORMAT, bitrate=None):
    frame_size = get_opus_frame_size(audio_format.rate)
    import opuslib  # pylint: disable=import-outside-toplevel
    encoder = opuslib.Encoder(audio_format.rate, audio_format.channels, 'audio')
    if bitrate is not None:
        encoder.bitrate = bitrate
    chunk_size = frame_size * audio_format.channels * audio_format.width
    opus_file.write(pack_number(len(audio_data), OPUS_PCM_LEN_SIZE))
    opus_file.write(pack_number(audio_format.rate, OPUS_RATE_SIZE))
    opus_file.write(pack_number(audio_format.channels, OPUS_CHANNELS_SIZE))
    opus_file.write(pack_number(audio_format.width, OPUS_WIDTH_SIZE))
    for i in range(0, len(audio_data), chunk_size):
        chunk = audio_data[i:i + chunk_size]
        # Preventing non-deterministic encoding results from uninitialized remainder of the encoder buffer
        if len(chunk) < chunk_size:
            chunk = chunk + b'\0' * (chunk_size - len(chunk))
        encoded = encoder.encode(chunk, frame_size)
        opus_file.write(pack_number(len(encoded), OPUS_CHUNK_LEN_SIZE))
        opus_file.write(encoded)
Example #10
0
        def worker():  # worker thread
            nonlocal loop, im, event, f
            pcm = im.tobytes()
            if len(pcm) % 2:
                pcm = b'\0' + pcm
            encoder = opuslib.Encoder(48000, 1, 'restricted_lowdelay')
            frames = []
            for x in range(0, len(pcm), 960 * 2):
                frames.append(encoder.encode(pcm[x:x + 960 * 2], 960))
            opcmlen = len(pcm)
            decoder = opuslib.Decoder(48000, 1)
            data = b''
            for frame in frames:
                data += decoder.decode(frame, 960)
            im = Image.frombytes(im.mode, im.size, data[len(data) - opcmlen:])
            im = im.convert("RGB")

            f = io.BytesIO()
            im.save(f, "JPEG")
            f.seek(0)
            loop.call_soon_threadsafe(event.set)
def generate_requests():
    try:
        with wave.open("../../audio/sample_3.wav") as f:
            frame_rate_is_valid(f.getframerate())
            yield build_first_request(f.getframerate(), f.getnchannels())
            frame_samples = f.getframerate() // 1000 * 60  # 60ms
            opus_encoder = opuslib.Encoder(f.getframerate(), f.getnchannels(),
                                           opuslib.APPLICATION_AUDIO)
            for data in iter(lambda: f.readframes(frame_samples),
                             b''):  # Send 60ms at a time
                if len(
                        data
                ) < frame_samples * 2:  # Padding last frame to closest allowed frame size
                    data = data.ljust(
                        get_padded_frame_size(frame_samples, f.getframerate())
                        * 2, b'\0')
                request = stt_pb2.StreamingRecognizeRequest()
                request.audio_content = opus_encoder.encode(
                    data,
                    len(data) >> 1)
                yield request
    except Exception as e:
        print("Got exception in generate_requests", e)
        raise
Example #12
0
def handle_post(in_data_raw, query_params, headers):
    global last_request_clock
    global first_client_write_clock
    global first_client_total_samples
    global first_client_value
    global global_volume
    global song_end_clock
    global song_start_clock

    # NOTE NOTE NOTE:
    # * All `clock` variables are measured in samples.
    # * All `clock` variables represent the END of an interval, NOT the
    #   beginning. It's arbitrary which one to use, but you have to be
    #   consistent, and trust me that it's slightly nicer this way.

    # Note: This will eventually create a precision problem for the JS
    #   clients, which are using floats. Specifically, at 44100 Hz, it will
    #   fail on February 17, 5206.
    server_clock = int(time.time() * SAMPLE_RATE)

    client_write_clock = query_params.get("write_clock", None)
    if client_write_clock is not None:
        client_write_clock = int(client_write_clock[0])
    client_read_clock = query_params.get("read_clock", None)
    if client_read_clock is not None:
        client_read_clock = int(client_read_clock[0])
    else:
        raise ValueError("no client read clock")

    n_samples = query_params.get("n_samples", None)
    if n_samples is not None:
        n_samples = int(n_samples[0])

    userid = None
    userids = query_params.get("userid", None)

    username = None
    usernames = query_params.get("username", None)
    if not userids or not usernames:
        raise ValueError("missing username/id")

    userid, = userids
    username, = usernames
    if not userid or not username:
        raise ValueError("missing username/id")

    if client_write_clock is None:
        # New session, write some debug info to disk
        logging.debug("*** New client:" + str(headers) + str(query_params) +
                      "\n\n")

    # This indicates a new session, so flush everything. (There's probably a better way to handle this.)
    prev_last_write_clock = None
    if (client_write_clock is None) and (userid in users):
        prev_last_write_clock = users[userid].last_write_clock
        del users[userid]

    update_users(userid, username, server_clock, client_read_clock)
    user = users[userid]
    if user.last_write_clock is None:
        user.last_write_clock = prev_last_write_clock

    volumes = query_params.get("volume", None)
    if volumes:
        volume, = volumes
        global_volume = math.exp(6.908 * float(volume)) / 1000

    msg_chats = query_params.get("chat", None)
    if msg_chats:
        msg_chats, = msg_chats
        msg_chats = json.loads(msg_chats)
        for other_userid, other_user in users.items():
            if other_userid != userid:
                for msg_chat in msg_chats:
                    other_user.chats_to_send.append((username, msg_chat))

    mic_volumes = query_params.get("mic_volume", None)
    if mic_volumes:
        mic_volume, = mic_volumes
        for other_userid, new_mic_volume in json.loads(mic_volume):
            if other_userid in users:
                if new_mic_volume > 2:
                    new_mic_volume = 2
                elif new_mic_volume < 0:
                    new_mic_volume = 0

                users[other_userid].mic_volume = new_mic_volume

                # https://www.dr-lex.be/info-stuff/volumecontrols.html
                # Make 1 be unity
                users[other_userid].scaled_mic_volume = math.exp(
                    6.908 * new_mic_volume * .5) / math.exp(6.908 * 0.5)

    if query_params.get("request_lead", None):
        assign_delays(userid)
        song_start_clock = None
        song_end_clock = 0

    if query_params.get("mark_start_singing", None):
        song_start_clock = user.last_write_clock
        song_end_clock = 0

    if query_params.get("mark_stop_singing", None):
        song_end_clock = user.last_write_clock

        # They're done singing, send them to the end.
        user.delay_to_send = max_position

    in_data = np.frombuffer(in_data_raw, dtype=np.uint8)

    # Audio from clients is summed, so we need to clear the circular
    #   buffer ahead of them. The range we are clearing was "in the
    #   future" as of the last request, and we never touch the future,
    #   so nothing has touched it yet "this time around".
    if last_request_clock is not None:
        clear_samples = min(server_clock - last_request_clock, QUEUE_LENGTH)
        wrap_assign(audio_queue, last_request_clock,
                    np.zeros(clear_samples, np.float32))
        wrap_assign(n_people_queue, last_request_clock,
                    np.zeros(clear_samples, np.int16))

    saved_last_request_clock = last_request_clock
    last_request_clock = server_clock

    if not user.opus_state:
        # initialize
        user.opus_state = (opuslib.Encoder(SAMPLE_RATE, CHANNELS,
                                           opuslib.APPLICATION_AUDIO),
                           opuslib.Decoder(SAMPLE_RATE, CHANNELS))
    (enc, dec) = user.opus_state

    # If the user does not send us any data, we will treat it as silence of length n_samples. This is useful if they are just starting up.
    if len(in_data) == 0:
        if n_samples is None:
            raise ValueError("Must provide either n_samples or data")
        in_data = np.zeros(n_samples, np.float32)
    else:
        packets = unpack_multi(in_data)
        decoded = []
        for p in packets:
            d = dec.decode_float(p.tobytes(),
                                 OPUS_FRAME_SAMPLES,
                                 decode_fec=False)
            decoded.append(np.frombuffer(d, np.float32))
        in_data = np.concatenate(decoded)

    # Sending n_samples is optional if data is sent, but in case of both they must match
    if n_samples is None:
        n_samples = len(in_data)
    if n_samples != len(in_data):
        raise ValueError("Client is confused about how many samples it sent")

    if client_write_clock is None:
        pass
    elif client_write_clock - n_samples < server_clock - QUEUE_LENGTH:
        # Client is too far behind and going to wrap the buffer. :-(
        raise ValueError("Client's write clock is too far in the past")
    else:
        if user.last_seen_write_clock is not None:
            # For debugging purposes only
            if client_write_clock - n_samples != user.last_seen_write_clock:
                raise ValueError(
                    f'Client write clock desync ('
                    f'{client_write_clock - n_samples} - '
                    f'{user.last_seen_write_clock} = '
                    f'{client_write_clock - n_samples - user.last_seen_write_clock})'
                )
            if user.last_write_clock <= song_end_clock <= client_write_clock:
                user.delay_to_send = max_position

        user.last_seen_write_clock = client_write_clock
        if client_write_clock is not None:
            user.last_write_clock = client_write_clock

        in_data *= user.scaled_mic_volume

        # Don't keep any input unless a song is in progress.
        if (song_start_clock and client_write_clock > song_start_clock
                and (not song_end_clock
                     or client_write_clock - n_samples < song_end_clock)):
            old_audio = wrap_get(audio_queue, client_write_clock - n_samples,
                                 n_samples)
            new_audio = old_audio + in_data
            wrap_assign(audio_queue, client_write_clock - n_samples, new_audio)

            old_n_people = wrap_get(n_people_queue,
                                    client_write_clock - n_samples, n_samples)
            new_n_people = old_n_people + np.ones(n_samples, np.int16)
            wrap_assign(n_people_queue, client_write_clock - n_samples,
                        new_n_people)

    # Why subtract n_samples above and below? Because the future is to the
    #   right. So when a client asks for n samples at time t, what they
    #   actually want is "the time interval ending at t", i.e. [t-n, t). Since
    #   the latest possible time they can ask for is "now", this means that
    #   the latest possible time interval they can get is "the recent past"
    #   instead of "the near future".
    # This doesn't matter to the clients if they all always use the same value of
    #   n_samples, but it matters if n_samples changes, and it matters for
    #   the server's zeroing.

    # For debugging purposes only
    if user.last_seen_read_clock is not None:
        if client_read_clock - n_samples != user.last_seen_read_clock:
            raise ValueError(
                f'Client read clock desync ('
                f'{client_read_clock - n_samples} - '
                f'{user.last_seen_read_clock} = '
                f'{client_read_clock - n_samples - user.last_seen_read_clock})'
            )
    user.last_seen_read_clock = client_read_clock

    if query_params.get("loopback", [None])[0] == "true":
        data = in_data
    else:
        data = wrap_get(audio_queue, client_read_clock - n_samples, n_samples)
        n_people = wrap_get(n_people_queue, client_read_clock - n_samples,
                            n_samples)

        # We could scale volume by having n_people be the number of
        # earlier people and then scale by a simple 1/n_people.  But a
        # curve of (1 + X) / (n_people + X) falls a bit less
        # dramatically and should sound better.
        #
        # Compare:
        #   https://www.wolframalpha.com/input/?i=graph+%281%29+%2F+%28x%29+from+1+to+10
        #   https://www.wolframalpha.com/input/?i=graph+%281%2B3%29+%2F+%28x%2B3%29+from+1+to+10
        data = data * (1 + N_PHANTOM_PEOPLE) / (n_people + N_PHANTOM_PEOPLE)

        data *= global_volume

    packets = data.reshape([-1, OPUS_FRAME_SAMPLES])
    encoded = []
    for p in packets:
        e = np.frombuffer(enc.encode_float(p.tobytes(), OPUS_FRAME_SAMPLES),
                          np.uint8)
        encoded.append(e)
    data = pack_multi(encoded).tobytes()

    x_audio_metadata = json.dumps({
        "server_clock": server_clock,
        "server_sample_rate": SAMPLE_RATE,
        "last_request_clock": saved_last_request_clock,
        "client_read_clock": client_read_clock,
        "client_write_clock": client_write_clock,
        "user_summary": user_summary(),
        "chats": user.chats_to_send,
        "delay_seconds": user.delay_to_send,
        "song_start_clock": song_start_clock,
        # Both the following uses units of 128-sample frames
        "queue_size": QUEUE_LENGTH / FRAME_SIZE,
    })

    user.chats_to_send.clear()
    user.delay_to_send = None

    return data, x_audio_metadata
Example #13
0
import sys
import time
import random
import numpy as np
import server
import server_wrapper
import opuslib

PACKET_INTERVAL = 0.6 # 600ms
PACKET_SAMPLES = int(server.SAMPLE_RATE * PACKET_INTERVAL)

enc = opuslib.Encoder(
  server.SAMPLE_RATE, server_wrapper.CHANNELS, opuslib.APPLICATION_AUDIO)
zeros = np.zeros(PACKET_SAMPLES).reshape(
  [-1, server_wrapper.OPUS_FRAME_SAMPLES])

data = server_wrapper.pack_multi([
  np.frombuffer(
    enc.encode_float(packet.tobytes(), server_wrapper.OPUS_FRAME_SAMPLES),
    np.uint8)
  for packet in zeros]).tobytes()

userid = int(random.random()*10000000)
username = "******"

def query_string():
  return "read_clock=%s&userid=%s&username=%s" % (
    (server.calculate_server_clock(),
     userid,
     username))
def handle_post(userid, n_samples, in_data_raw,
                query_string, print_status=True, client_address=None) -> Tuple[Any, str]:
    if not userid.isdigit():
        raise ValueError("UserID must be numeric; got: %r"%userid)
    try:
        enc, dec = users[userid]
    except KeyError:
        enc = opuslib.Encoder(server.SAMPLE_RATE, CHANNELS,
                              opuslib.APPLICATION_AUDIO)
        dec = opuslib.Decoder(server.SAMPLE_RATE, CHANNELS)
        users[userid] = enc, dec

    in_data = np.frombuffer(in_data_raw, dtype=np.uint8)

    # If the user does not send us any data, we will treat it as silence of length n_samples. This is useful if they are just starting up.
    client_no_data = len(in_data)==0
    if client_no_data:
        if n_samples == 0:
            raise ValueError("Must provide either n_samples or data")
        in_data = np.zeros(n_samples, np.float32)
    else:
        packets = unpack_multi(in_data)
        decoded = []
        for p in packets:
            d = dec.decode_float(p.tobytes(), OPUS_FRAME_SAMPLES, decode_fec=False)
            decoded.append(np.frombuffer(d, np.float32))
        in_data = np.concatenate(decoded)

    # Sending n_samples is optional if data is sent, but in case of both they must match
    if n_samples == 0:
        n_samples = len(in_data)
    if n_samples != len(in_data):
        raise ValueError("Client is confused about how many samples it sent (got %s expected %s" % (n_samples, len(in_data)))

    rms_volume = calculate_volume(in_data)
    # This is only safe because query_string is guaranteed to already contain
    #   at least the userid parameter.
    query_string += '&rms_volume=%s'%rms_volume

    data, x_audio_metadata = handle_json_post(
        in_data, query_string, print_status, client_address=client_address)

    # Divide data into user_summary and raw audio data
    n_users_in_summary, = struct.unpack(">H", data[:2])
    user_summary_n_bytes = server.summary_length(n_users_in_summary)

    user_summary = data[:user_summary_n_bytes]
    raw_audio = data[user_summary_n_bytes:].view(np.float32)

    # Encode raw audio
    packets = raw_audio.reshape([-1, OPUS_FRAME_SAMPLES])
    encoded = []
    for p in packets:
        e = np.frombuffer(enc.encode_float(p.tobytes(), OPUS_FRAME_SAMPLES), np.uint8)
        encoded.append(e)
    compressed_audio = pack_multi(encoded)

    # Combine user_summary and compressed audio data
    data = np.append(user_summary, compressed_audio)

    with open(os.path.join(LOG_DIR, userid), "a") as log_file:
        log_file.write("%d %.8f\n"%(
            time.time(),
            -1 if client_no_data else rms_volume))

    return data.tobytes(), x_audio_metadata
Example #15
0
 def test_reset_state(cls):
     encoder = opuslib.Encoder(48000, 2, opuslib.APPLICATION_AUDIO)
     encoder.reset_state()
Example #16
0
    pcm = pcm.readframes(2880)
    print(len(pcm))

    wave_out = wave.open('wav_out1.wav', 'w')
    wave_out.setnchannels(2)
    wave_out.setsampwidth(2)
    wave_out.setframerate(48000)
    wave_out.writeframes(pcm)
    wave_out.close()

    #framesize is per channel samples, but max is 60ms frame, ie 2880
    # not particularly good for storage, since we need to break it up into
    # many frames

    encoder = opuslib.Encoder(48000, 2, opuslib.APPLICATION_AUDIO)
    opus_encode = encoder.encode(pcm_data=pcm, frame_size=2880)
    print(len(opus_encode))

    decoder = opuslib.Decoder(48000, 2)
    opus_decode = decoder.decode(opus_data=opus_encode, frame_size=2880)
    print(len(opus_decode))

    #raw = struct.unpack('h' * (len(opus_decode)//2), opus_decode)
    #raw = raw[0::2]
    #print(len(raw))

    out = wave.open('wav_out2.wav', 'w')
    out.setnchannels(2)
    out.setsampwidth(2)
    out.setframerate(48000)
Example #17
0
 def __init__(self, samples=48000, frames=960, channels=1):
     self.frames = frames
     self.encoder = opuslib.Encoder(samples, channels,
                                    opuslib.APPLICATION_VOIP)
     self.decoder = opuslib.Decoder(samples, channels)
Example #18
0
def understand_audio(ncs_client,
                     loop,
                     recorder,
                     user_id,
                     context_tag=None,
                     language='eng-USA'):
    audio_type = "audio/opus;rate=%d" % recorder.rate

    # Useful terminology reference:
    # https://larsimmisch.github.io/pyalsaaudio/terminology.html
    bytes_per_frame = recorder.channels * SAMPLE_SIZE
    audio_packet_min_size = FRAME_SIZE * bytes_per_frame
    audio_packet_max_size = 4 * audio_packet_min_size

    try:
        yield from ncs_client.connect()
        session = yield from ncs_client.init_session(user_id,
                                                     DEVICE_ID,
                                                     codec=audio_type)
        transaction = yield from session.begin_transaction(
            command='NDSP_ASR_APP_CMD',
            language=language,
            context_tag=context_tag)

        audio_transfer = NCSAudioTransfer(id_=session.get_new_audio_id(),
                                          session=session)
        yield from transaction.send_parameter(name='AUDIO_INFO',
                                              type_='audio',
                                              value=audio_transfer.info)
        # We end the transaction here, but we will only have a 'query_end' response
        # back when the audio transfer and ASR/NLU are done.
        yield from transaction.end(wait=False)
        yield from audio_transfer.begin()

        key_event = asyncio.Event()

        def key_event_callback():
            sys.stdin.readline()
            key_event.set()
            recorder.stop()
            loop.remove_reader(sys.stdin)

        loop.add_reader(sys.stdin, key_event_callback)

        key_task = asyncio.ensure_future(key_event.wait())
        audio_task = asyncio.ensure_future(recorder.audio_queue.get())

        raw_audio = bytearray()
        mono_audio = bytearray()

        encoder = opuslib.Encoder(
            fs=recorder.rate,
            channels=1,
            application=opuslib.api.constants.APPLICATION_VOIP)

        recorder.start()
        print('Recording, press Enter to stop...')
        while not key_task.done() and (int(time.time()) < audio_timer):
            while len(raw_audio) > audio_packet_min_size:
                count = min(len(raw_audio), audio_packet_max_size)
                mono_audio += convert_to_mono(raw_audio, count,
                                              recorder.channels, SAMPLE_SIZE)
                raw_audio = raw_audio[count:]

            while len(mono_audio) > FRAME_SIZE * SAMPLE_SIZE:
                audio_to_encode = bytes(mono_audio[:FRAME_SIZE * SAMPLE_SIZE])
                audio_encoded = encoder.encode(audio_to_encode, FRAME_SIZE)
                yield from audio_transfer.send_bytes(audio_encoded)
                mono_audio = mono_audio[FRAME_SIZE * SAMPLE_SIZE:]

            yield from asyncio.wait((key_task, audio_task),
                                    return_when=asyncio.FIRST_COMPLETED,
                                    loop=loop)

            if audio_task.done() or (int(time.time()) >= audio_timer):
                raw_audio += audio_task.result()
                audio_task = asyncio.ensure_future(recorder.audio_queue.get())

        audio_task.cancel()

        yield from audio_transfer.end(wait=False)
        yield from transaction.wait_for_query_end()
    finally:
        yield from ncs_client.close()
Example #19
0
# ZeroMQ Declaration
url = '*'
port = 8080
sio = socketio.AsyncServer(async_mode='aiohttp', cors_allowed_origins='*')
app = web.Application()
sio.attach(app)

# Radio-Core Declaration
tuner = Tuner(stations, sfs, cuda=cuda)
demod = [WBFM(tau, r['bw'], r['afs'], r['bw'], cuda=cuda) for r in stations]
queue = asyncio.Queue()
sdr_buff = 1200

# OPUS Declaration
opus = [opuslib.Encoder(r['afs'], r['chs'], r['codec']) for r in stations]

# Radio Declaration
args = dict(driver="lime")
sdr = SoapySDR.Device(args)
sdr.setGainMode(SOAPY_SDR_RX, 0, True)
sdr.setSampleRate(SOAPY_SDR_RX, 0, tuner.bw)
sdr.setFrequency(SOAPY_SDR_RX, 0, tuner.mdf)

# Buffer Declaration
if cuda:
    sig = importlib.import_module('cusignal')
    buff = sig.get_shared_mem(tuner.size, dtype=np.complex64)
else:
    buff = np.zeros([tuner.size], dtype=np.complex64)