From b534e2b731466d231efe8e1685e78683567dd68f Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Thu, 17 Mar 2022 22:41:37 -0400 Subject: [PATCH 01/45] Typo --- NoiseGate-v2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NoiseGate-v2.py b/NoiseGate-v2.py index a06e0c5..7381b52 100644 --- a/NoiseGate-v2.py +++ b/NoiseGate-v2.py @@ -7,11 +7,11 @@ from threading import Thread sound_buffer = [] -class AudioSteam(Thread): +class AudioStream(Thread): def __init__(self, _channels: int = 1, _sample_rate: int = 48000, _frames_per_buffer: int = 2048, _input_device_index: int = None, _output_device_index: int = None, _input: bool = True, _output: bool = True): - super(AudioSteam, self).__init__() + super(AudioStream, self).__init__() self.paInstance_kwargs = { 'format': pyaudio.paFloat32, 'channels': _channels, @@ -91,7 +91,7 @@ class AudioSteam(Thread): self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name')) -class NoiseGate(AudioSteam): +class NoiseGate(AudioStream): def __init__(self, **kwargs): super().__init__(**kwargs) -- 2.49.1 From 2dacab263bc78e3f7417c7edb3773f6bdcfb2677 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 20 Mar 2022 03:05:33 -0400 Subject: [PATCH 02/45] Rename to resolve conflict --- NoiseGate-v2.py => NoiseGatev2.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename NoiseGate-v2.py => NoiseGatev2.py (100%) diff --git a/NoiseGate-v2.py b/NoiseGatev2.py similarity index 100% rename from NoiseGate-v2.py rename to NoiseGatev2.py -- 2.49.1 From 465c0e00ea09e8c05de8b730007f5bf0e52462b6 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sat, 26 Mar 2022 01:35:02 -0400 Subject: [PATCH 03/45] Added noisegate to the 'sound' file and integrated it with its function --- bot.py | 6 ++---- sound.py | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/bot.py b/bot.py index 6d9576b..5be70d8 100644 --- a/bot.py +++ b/bot.py @@ -95,13 +95,11 @@ class Bot(commands.Bot): voice_connection = await channel.connect() # Create an audio stream from selected device - self.streamHandler = sound.PCMStream(self.DEVICE_ID) + self.streamHandler = sound.PCMStream(self.DEVICE_ID, voice_connection) + # Start the audio stream await self.streamHandler.play() - # Play the stream - voice_connection.play(discord.PCMAudio(self.streamHandler)) - # Start the SDR and begin playing to the audio stream self.start_sdr() diff --git a/sound.py b/sound.py index c33d97e..cd6d46e 100644 --- a/sound.py +++ b/sound.py @@ -1,5 +1,7 @@ +import threading import time - +import audioop +import discord import sounddevice import sounddevice as sd from pprint import pformat @@ -13,14 +15,18 @@ sd.default.samplerate = 48000 class PCMStream: globals() - def __init__(self, _device_id): + def __init__(self, _device_id, _voice_connection): self.stream = sd.RawInputStream(device=_device_id) + self.NoiseGate = NoiseGate(_voice_connection, self) def change_device(self, _device_id): self.clean_up() self.stream = sd.RawInputStream(device=_device_id) + async def connect(self): + self.NoiseGate.start() + # Stops and destroys the current stream def clean_up(self): if not self.stream.closed: @@ -43,11 +49,27 @@ class PCMStream: # frame is 4 bytes frames = int(num_bytes / 4) data = self.stream.read(frames)[0] - # convert to pcm format return bytes(data) +class NoiseGate(threading.Thread): + def __init__(self, _voice_connection, _pcmstream_instance): + super().__init__() + self.voice_connection = _voice_connection + self.PCMStream_Instance = _pcmstream_instance + + def run(self) -> None: + while self.voice_connection.is_connected(): + if float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2)) >= 5: + # Play the stream + self.voice_connection.play(discord.PCMAudio(self.PCMStream_Instance)) + while float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2)) >= 5: + time.sleep(.5) + self.voice_connection.stop() + time.sleep(.1) + + class DeviceNotFoundError(Exception): def __init__(self): self.devices = sd.query_devices() @@ -73,4 +95,8 @@ def query_devices(): if not options: raise DeviceNotFoundError() - return options \ No newline at end of file + return options + + + + -- 2.49.1 From a13cf36e157051363903cf0cc56b17f4c7da9d53 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sat, 26 Mar 2022 02:24:06 -0400 Subject: [PATCH 04/45] Actually connecting the noisegate --- NoiseGate.py | 67 ---------------------------------------------------- 1 file changed, 67 deletions(-) delete mode 100644 NoiseGate.py diff --git a/NoiseGate.py b/NoiseGate.py deleted file mode 100644 index 70e8171..0000000 --- a/NoiseGate.py +++ /dev/null @@ -1,67 +0,0 @@ -import threading -import time - -import numpy as np -import discord -import sounddevice as sd -from threading import Thread, Event - -noise_gate_trigger = 0 # Set this value for the trigger on the noise-gate -voice_connection = None -audio_stream = None -last_callback_value = 0 - - -class NoiseGate(Thread): - def __init__(self, trigger_value: int = 700): - global noise_gate_trigger - super(NoiseGate, self).__init__() - self.stream = None - self.stop_NG = threading.Event() - self.NG_Started = threading.Event() - noise_gate_trigger = trigger_value - - def init_stream(self, num, _voice_connection, _audio_stream): - global voice_connection, audio_stream - self.stream = sd.InputStream(device=num, callback=stream_callback) - voice_connection = _voice_connection - audio_stream = _audio_stream - - def run(self) -> None: - self.NG_Started.set() - self.stream.start() - while not self.stop_NG.is_set(): - #print("Main loop start") - if last_callback_value >= noise_gate_trigger: - trigger_noise_gate(True) - while last_callback_value >= noise_gate_trigger: - time.sleep(6) - trigger_noise_gate(False) - #print("Main loop end") - - self.stream.stop() - self.stream.close() - self.NG_Started.clear() - voice_connection.stop() - print('Thread #%s stopped' % self.ident) - - -def stream_callback(indata, *args): - global last_callback_value - volume_normalization = np.linalg.norm(indata) * 10 - last_callback_value = int(volume_normalization) - #print(f"Callback Value: {last_callback_value}") - - -def trigger_noise_gate(triggered: bool): - if triggered: - if not voice_connection.is_playing(): - voice_connection.play(discord.PCMAudio(audio_stream)) - # print("|" * int(volume_normalization / 4)) - print("Noise Gate was Triggered") - #time.sleep(10) - else: - if voice_connection.is_playing(): - print("Noise Gate stopped") - voice_connection.pause() - # try disconnecting and reconnecting -- 2.49.1 From 7a9dbfb53a9d8ed78eab7ade7aa6d9c46ca57cd8 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sat, 26 Mar 2022 02:24:06 -0400 Subject: [PATCH 05/45] Actually connecting the noisegate --- NoiseGate.py | 67 ---------------------------------------------------- sound.py | 2 ++ 2 files changed, 2 insertions(+), 67 deletions(-) delete mode 100644 NoiseGate.py diff --git a/NoiseGate.py b/NoiseGate.py deleted file mode 100644 index 70e8171..0000000 --- a/NoiseGate.py +++ /dev/null @@ -1,67 +0,0 @@ -import threading -import time - -import numpy as np -import discord -import sounddevice as sd -from threading import Thread, Event - -noise_gate_trigger = 0 # Set this value for the trigger on the noise-gate -voice_connection = None -audio_stream = None -last_callback_value = 0 - - -class NoiseGate(Thread): - def __init__(self, trigger_value: int = 700): - global noise_gate_trigger - super(NoiseGate, self).__init__() - self.stream = None - self.stop_NG = threading.Event() - self.NG_Started = threading.Event() - noise_gate_trigger = trigger_value - - def init_stream(self, num, _voice_connection, _audio_stream): - global voice_connection, audio_stream - self.stream = sd.InputStream(device=num, callback=stream_callback) - voice_connection = _voice_connection - audio_stream = _audio_stream - - def run(self) -> None: - self.NG_Started.set() - self.stream.start() - while not self.stop_NG.is_set(): - #print("Main loop start") - if last_callback_value >= noise_gate_trigger: - trigger_noise_gate(True) - while last_callback_value >= noise_gate_trigger: - time.sleep(6) - trigger_noise_gate(False) - #print("Main loop end") - - self.stream.stop() - self.stream.close() - self.NG_Started.clear() - voice_connection.stop() - print('Thread #%s stopped' % self.ident) - - -def stream_callback(indata, *args): - global last_callback_value - volume_normalization = np.linalg.norm(indata) * 10 - last_callback_value = int(volume_normalization) - #print(f"Callback Value: {last_callback_value}") - - -def trigger_noise_gate(triggered: bool): - if triggered: - if not voice_connection.is_playing(): - voice_connection.play(discord.PCMAudio(audio_stream)) - # print("|" * int(volume_normalization / 4)) - print("Noise Gate was Triggered") - #time.sleep(10) - else: - if voice_connection.is_playing(): - print("Noise Gate stopped") - voice_connection.pause() - # try disconnecting and reconnecting diff --git a/sound.py b/sound.py index cd6d46e..ee2c76e 100644 --- a/sound.py +++ b/sound.py @@ -42,6 +42,7 @@ class PCMStream: async def play(self): if not self.stream.active: self.stream.start() + await self.connect() # call back read function for the stream def read(self, num_bytes): @@ -61,6 +62,7 @@ class NoiseGate(threading.Thread): def run(self) -> None: while self.voice_connection.is_connected(): + print(f"Volume: '{float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2)) >= 5}'") if float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2)) >= 5: # Play the stream self.voice_connection.play(discord.PCMAudio(self.PCMStream_Instance)) -- 2.49.1 From b444236dc9134176c33a172cdb24edf51ebcfa23 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sat, 26 Mar 2022 02:39:08 -0400 Subject: [PATCH 06/45] Printing volume value --- sound.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound.py b/sound.py index ee2c76e..58cae79 100644 --- a/sound.py +++ b/sound.py @@ -62,7 +62,7 @@ class NoiseGate(threading.Thread): def run(self) -> None: while self.voice_connection.is_connected(): - print(f"Volume: '{float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2)) >= 5}'") + print(f"Volume: '{float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2))}'") if float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2)) >= 5: # Play the stream self.voice_connection.play(discord.PCMAudio(self.PCMStream_Instance)) -- 2.49.1 From 48f6812f68db24c6c97153ee9e3032b4df3b7907 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sat, 26 Mar 2022 02:42:42 -0400 Subject: [PATCH 07/45] Printing volume value --- sound.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sound.py b/sound.py index 58cae79..d65f134 100644 --- a/sound.py +++ b/sound.py @@ -62,6 +62,7 @@ class NoiseGate(threading.Thread): def run(self) -> None: while self.voice_connection.is_connected(): + print(f"Raw data: '{self.PCMStream_Instance.read(16)}'") print(f"Volume: '{float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2))}'") if float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2)) >= 5: # Play the stream -- 2.49.1 From 0329ff7a813f43e57f3cad2b1d76ec1b116249f8 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sat, 26 Mar 2022 03:07:24 -0400 Subject: [PATCH 08/45] New attempt --- sound.py | 77 ++++++++++++++++++++++++++------------------------------ 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/sound.py b/sound.py index d65f134..9bc76c3 100644 --- a/sound.py +++ b/sound.py @@ -12,47 +12,6 @@ sd.default.dtype = "int16" sd.default.latency = "low" sd.default.samplerate = 48000 -class PCMStream: - globals() - - def __init__(self, _device_id, _voice_connection): - self.stream = sd.RawInputStream(device=_device_id) - self.NoiseGate = NoiseGate(_voice_connection, self) - - def change_device(self, _device_id): - self.clean_up() - - self.stream = sd.RawInputStream(device=_device_id) - - async def connect(self): - self.NoiseGate.start() - - # Stops and destroys the current stream - def clean_up(self): - if not self.stream.closed: - self.stream.stop(ignore_errors=True) - self.stream.close(ignore_errors=True) - - # Stops the current running stream but does not destroy it - async def pause(self): - if self.stream.active: - self.stream.stop(ignore_errors=True) - - # Plays the stream - async def play(self): - if not self.stream.active: - self.stream.start() - await self.connect() - - # call back read function for the stream - def read(self, num_bytes): - if self.stream.active: - # frame is 4 bytes - frames = int(num_bytes / 4) - data = self.stream.read(frames)[0] - # convert to pcm format - return bytes(data) - class NoiseGate(threading.Thread): def __init__(self, _voice_connection, _pcmstream_instance): @@ -73,6 +32,42 @@ class NoiseGate(threading.Thread): time.sleep(.1) +class PCMStream(NoiseGate): + globals() + def __init__(self, _device_id, _voice_connection): + super(PCMStream, self).__init__(_pcmstream_instance=self, _voice_connection=_voice_connection) + self.stream = sd.RawInputStream(device=_device_id) + + def change_device(self, _device_id): + self.clean_up() + self.stream = sd.RawInputStream(device=_device_id) + + # Stops and destroys the current stream + def clean_up(self): + if not self.stream.closed: + self.stream.stop(ignore_errors=True) + self.stream.close(ignore_errors=True) + + # Stops the current running stream but does not destroy it + async def pause(self): + if self.stream.active: + self.stream.stop(ignore_errors=True) + + # Plays the stream + async def play(self): + if not self.stream.active: + self.stream.start() + self.start() + + # call back read function for the stream + def read(self, num_bytes): + if self.stream.active: + # frame is 4 bytes + frames = int(num_bytes / 4) + data = self.stream.read(frames)[0] + # convert to pcm format + return bytes(data) + class DeviceNotFoundError(Exception): def __init__(self): self.devices = sd.query_devices() -- 2.49.1 From 24adc47109088465b6d5202553a61112eb9fda1a Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 00:50:42 -0400 Subject: [PATCH 09/45] Dan's Update - New classes for noisegate & audio stream - Ability to manipulate raw data in real-time --- BotResources.py | 2 +- NoiseGatev2.py | 151 +++++++++++++++++++++++++++++++++--------------- bot.py | 44 +++++++++----- sound.py | 100 -------------------------------- 4 files changed, 134 insertions(+), 163 deletions(-) delete mode 100644 sound.py diff --git a/BotResources.py b/BotResources.py index bcfab85..5761c8c 100644 --- a/BotResources.py +++ b/BotResources.py @@ -1,6 +1,6 @@ -import sound import configparser from os.path import exists +from NoiseGatev2 import AudioStream PDB_ACCEPTABLE_HANDLERS = {'gqrx': { 'Modes': ['wfm', 'fm'] diff --git a/NoiseGatev2.py b/NoiseGatev2.py index 7381b52..9655a6a 100644 --- a/NoiseGatev2.py +++ b/NoiseGatev2.py @@ -1,25 +1,24 @@ +import audioop +import math import pyaudio -import struct +import discord import numpy -import time -from threading import Thread -sound_buffer = [] +THRESHOLD = 50 +voice_connection = None -class AudioStream(Thread): - def __init__(self, _channels: int = 1, _sample_rate: int = 48000, _frames_per_buffer: int = 2048, +class AudioStream: + def __init__(self, _channels: int = 2, _sample_rate: int = 48000, _frames_per_buffer: int = 1024, _input_device_index: int = None, _output_device_index: int = None, _input: bool = True, - _output: bool = True): - super(AudioStream, self).__init__() + _output: bool = True, _init_on_startup: bool = True): self.paInstance_kwargs = { - 'format': pyaudio.paFloat32, + 'format': pyaudio.paInt16, 'channels': _channels, 'rate': _sample_rate, 'input': _input, 'output': _output, - 'frames_per_buffer': _frames_per_buffer, - 'stream_callback': callback + 'frames_per_buffer': _frames_per_buffer } if _input_device_index: @@ -36,15 +35,18 @@ class AudioStream(Thread): print(f"[AudioStream.__init__]:\tOutput was not enabled." f" Reinitialize with '_output=True'") - # Init PyAudio instance - self.paInstance = pyaudio.PyAudio() + if _init_on_startup: + # Init PyAudio instance + print("Creating PyAudio instance") + self.paInstance = pyaudio.PyAudio() - # Define and initialize stream object if we have been passed a device ID (pyaudio.open) - self.stream = None - if _output_device_index and _input_device_index: - self.init_stream() + # Define and initialize stream object if we have been passed a device ID (pyaudio.open) + self.stream = None - # temp section + if _output_device_index or _input_device_index: + if _init_on_startup: + print("Init stream") + self.init_stream() def init_stream(self, _new_output_device_index: int = None, _new_input_device_index: int = None): # Check what device was asked to be changed (or set) @@ -64,7 +66,7 @@ class AudioStream(Thread): self.close_if_open() - # Reopen the stream + # Open the stream self.stream = self.paInstance.open(**self.paInstance_kwargs) def close_if_open(self): @@ -75,56 +77,109 @@ class AudioStream(Thread): self.stream.close() print(f"[ReopenStream.close_if_open]:\t Stream was open; It was closed.") - def list_devices(self, _show_input_devices: bool = True, _show_output_devices: bool = True): + def list_devices(self, _display_input_devices: bool = True, _display_output_devices: bool = True): info = self.paInstance.get_host_api_info_by_index(0) numdevices = info.get('deviceCount') + devices = { + 'Input': {}, + 'Output': {} + } for i in range(0, numdevices): if (self.paInstance.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0: - if _show_input_devices: - print("Input Device id ", i, " - ", - self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name')) + input_device = self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name') + devices['Input'][i] = input_device + if _display_input_devices: + print("Input Device id ", i, " - ", input_device) if (self.paInstance.get_device_info_by_host_api_device_index(0, i).get('maxOutputChannels')) > 0: - if _show_output_devices: - print("Output Device id ", i, " - ", - self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name')) + output_device = self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name') + devices['Output'][i] = output_device + if _display_output_devices: + print("Output Device id ", i, " - ", output_device) + return devices -class NoiseGate(AudioStream): - def __init__(self, **kwargs): - super().__init__(**kwargs) - - def run(self) -> None: - # Start the audio stream - self.stream.start_stream() - - global sound_buffer - # While the stream is running, display the stream buffer in floats? - while self.stream.is_active(): - if len(sound_buffer) > 0: - for buffer in sound_buffer: - volume_normalization = numpy.linalg.norm(numpy.fromstring(buffer)) * 10 - print(str(float(volume_normalization))) - - self.stream.stop_stream() + async def stop(self): + await voice_connection.disconnect() + self.close_if_open() self.stream.close() - self.paInstance.terminate() -def callback(in_data, frame_count, time_info, status): - global sound_buffer +class NoiseGate(AudioStream): + def __init__(self, _voice_connection, **kwargs): + super(NoiseGate, self).__init__(_init_on_startup=True, **kwargs) + global voice_connection + voice_connection = _voice_connection + self.NGStream = NoiseGateStream(self) - sound_buffer.append(in_data) + def run(self) -> None: + global voice_connection + # Start the audio stream + self.stream.start_stream() + voice_connection.play(self.NGStream) - return in_data, pyaudio.paContinue + async def close(self): + await voice_connection.disconnect() + if self.stream.is_active: + self.stream.stop_stream() + +class NoiseGateStream(discord.AudioSource): + def __init__(self, _stream): + super(NoiseGateStream, self).__init__() + self.stream = _stream # The actual audio stream object + self.NG_fadeout = 480/20 # Fadeout value used to hold the noisegate after de-triggering + self.NG_fadeout_count = 0 # A count set when the noisegate is triggered and was de-triggered + self.process_set_count = 0 # Counts how many processes have been made in order to limit the prints + + def read(self): + try: + while voice_connection.is_connected(): + curr_buffer = bytearray(self.stream.stream.read(960)) + buffer_rms = audioop.rms(curr_buffer, 2) + if buffer_rms > 0: + buffer_decibel = 20 * math.log10(buffer_rms) + + if self.process_set_count % 25 == 0: + print(f"{buffer_decibel} db") + + if buffer_decibel >= THRESHOLD: + self.NG_fadeout_count = self.NG_fadeout + self.process_set_count += 1 + + return bytes(curr_buffer) + + else: + if self.NG_fadeout_count > 0: + self.NG_fadeout_count -= 1 + print(f"Frames in fadeout remaining: {self.NG_fadeout_count}") + self.process_set_count += 1 + + return bytes(curr_buffer) + + except OSError as e: + pass + + def audio_datalist_set_volume(self, datalist, volume): + """ Change value of list of audio chunks """ + sound_level = (volume / 100.) + + for i in range(len(datalist)): + chunk = numpy.fromstring(datalist[i], numpy.int16) + + chunk = chunk * sound_level + + datalist[i] = chunk.astype(numpy.int16) if __name__ == '__main__': + input_index = int(input("Input:\t")) output_index = int(input("Output:\t")) ng = NoiseGate(_input_device_index=input_index, _output_device_index=output_index) + ng.list_devices() + ng.start() diff --git a/bot.py b/bot.py index 5be70d8..1f080eb 100644 --- a/bot.py +++ b/bot.py @@ -3,8 +3,8 @@ import os import platform import discord import BotResources -import sound import configparser +import NoiseGatev2 from discord.ext import commands @@ -33,7 +33,9 @@ class Bot(commands.Bot): self.Bot_Connected = False # Init the audio devices list - self.Devices_List = sound.query_devices().items() + #self.Devices_List = sound.query_devices().items() + self.Devices_List = NoiseGatev2.AudioStream().list_devices(_display_input_devices=False, + _display_output_devices=False) # Init radio parameters self.profile_name = None @@ -79,6 +81,7 @@ class Bot(commands.Bot): brief="Joins the voice channel that the caller is in") async def join(ctx, *, member: discord.Member = None): member = member or ctx.author.display_name + print(f"Join requested by {member}") if not self.Bot_Connected: # Wait for the bot to be ready to connect @@ -89,45 +92,52 @@ class Bot(commands.Bot): if discord.opus.is_loaded(): channel = ctx.author.voice.channel + print("Sending hello") await ctx.send(f"Ok {str(member).capitalize()}, I'm joining {channel}") # Join the voice channel with the audio stream + print('Joining') voice_connection = await channel.connect() # Create an audio stream from selected device - self.streamHandler = sound.PCMStream(self.DEVICE_ID, voice_connection) - + print("Starting noisegate/stream handler") + self.streamHandler = NoiseGatev2.NoiseGate(_input_device_index=self.DEVICE_ID, + _voice_connection=voice_connection) # Start the audio stream - await self.streamHandler.play() + self.streamHandler.run() # Start the SDR and begin playing to the audio stream + print("Starting SDR") self.start_sdr() # Change the activity to the channel and band-type being used + print("Changing presence") await self.set_activity() # 'Lock' the bot from connecting + print("Locking the bot") self.Bot_Connected = True else: # Return that the opus library would not load await ctx.send("Opus won't load") + print("OPUS didn't load properly") else: await ctx.send(f"{str(member).capitalize()}, I'm already connected") + print("Bot is already in a channel") @self.command(help="Use this command to have the bot leave your channel", brief="Leaves the current voice channel") async def leave(ctx, member: discord.Member = None): member = member or ctx.author.display_name - if self.Bot_Connected: - print("Cleaning up") - # Stop the sound handlers - await self.streamHandler.pause() + print(f"Leave requested by {member}") - print("Disconnecting") + if self.Bot_Connected: + # Stop the sound handlers # Disconnect the client from the voice channel - await ctx.voice_client.disconnect() + print("Disconnecting") + await self.streamHandler.close() print("Changing presence") # Change the presence to away and '@ me' @@ -316,26 +326,29 @@ class Bot(commands.Bot): # Load the proper OPUS library for the device being used def load_opus(self): # Check the system type and load the correct library - # Linux ARM AARCH64 running 32bit OS if self.system_os_type == 'Linux_ARMv7l': + print(f"Loaded OPUS library for {self.system_os_type}") discord.opus.load_opus('./opus/libopus_armv7l.so') # Linux ARM AARCH64 running 64bit OS if self.system_os_type == 'Linux_AARCH64': + print(f"Loaded OPUS library for {self.system_os_type}") discord.opus.load_opus('./opus/libopus_aarcch64.so') # Windows 64bit if self.system_os_type == 'Windows_x64': + print(f"Loaded OPUS library for {self.system_os_type}") discord.opus.load_opus('./opus/libopus_amd64.dll') # Check to make sure the selected device is still available and has not changed its index def check_device(self, _override): # Check to see if an override has been passed if not _override: - for device, index in self.Devices_List: + print(f"Device list {self.Devices_List}") + for device, index in self.Devices_List['Input']: if int(index) == self.DEVICE_ID and str(device) == self.DEVICE_NAME: return True - for device, index in self.Devices_List: + for device, index in self.Devices_List['Input']: if str(device) == self.DEVICE_NAME: self.DEVICE_ID = int(index) return True @@ -376,11 +389,14 @@ class Bot(commands.Bot): if os.name == 'nt': if processor == "AMD64": self.system_os_type = 'Windows_x64' + print(f"OS/Arch is {self.system_os_type}") else: if processor == "aarch64": self.system_os_type = 'Linux_AARCH64' + print(f"OS/Arch is {self.system_os_type}") elif processor == "armv7l": self.system_os_type = 'Linux_ARMv7l' + print(f"OS/Arch is {self.system_os_type}") # Check to see if there is only one frequency def start_sdr(self): diff --git a/sound.py b/sound.py deleted file mode 100644 index 9bc76c3..0000000 --- a/sound.py +++ /dev/null @@ -1,100 +0,0 @@ -import threading -import time -import audioop -import discord -import sounddevice -import sounddevice as sd -from pprint import pformat - -DEFAULT = 0 -sd.default.channels = 2 -sd.default.dtype = "int16" -sd.default.latency = "low" -sd.default.samplerate = 48000 - - -class NoiseGate(threading.Thread): - def __init__(self, _voice_connection, _pcmstream_instance): - super().__init__() - self.voice_connection = _voice_connection - self.PCMStream_Instance = _pcmstream_instance - - def run(self) -> None: - while self.voice_connection.is_connected(): - print(f"Raw data: '{self.PCMStream_Instance.read(16)}'") - print(f"Volume: '{float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2))}'") - if float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2)) >= 5: - # Play the stream - self.voice_connection.play(discord.PCMAudio(self.PCMStream_Instance)) - while float(20 * audioop.rms(self.PCMStream_Instance.read(16), 2)) >= 5: - time.sleep(.5) - self.voice_connection.stop() - time.sleep(.1) - - -class PCMStream(NoiseGate): - globals() - def __init__(self, _device_id, _voice_connection): - super(PCMStream, self).__init__(_pcmstream_instance=self, _voice_connection=_voice_connection) - self.stream = sd.RawInputStream(device=_device_id) - - def change_device(self, _device_id): - self.clean_up() - self.stream = sd.RawInputStream(device=_device_id) - - # Stops and destroys the current stream - def clean_up(self): - if not self.stream.closed: - self.stream.stop(ignore_errors=True) - self.stream.close(ignore_errors=True) - - # Stops the current running stream but does not destroy it - async def pause(self): - if self.stream.active: - self.stream.stop(ignore_errors=True) - - # Plays the stream - async def play(self): - if not self.stream.active: - self.stream.start() - self.start() - - # call back read function for the stream - def read(self, num_bytes): - if self.stream.active: - # frame is 4 bytes - frames = int(num_bytes / 4) - data = self.stream.read(frames)[0] - # convert to pcm format - return bytes(data) - -class DeviceNotFoundError(Exception): - def __init__(self): - self.devices = sd.query_devices() - self.host_apis = sd.query_hostapis() - super().__init__("No Devices Found") - - def __str__(self): - return ( - f"Devices \n" - f"{self.devices} \n " - f"Host APIs \n" - f"{pformat(self.host_apis)}" - ) - - -def query_devices(): - options = { - device.get("name"): index - for index, device in enumerate(sd.query_devices()) - if (device.get("max_input_channels") > 0 and device.get("hostapi") == DEFAULT) - } - - if not options: - raise DeviceNotFoundError() - - return options - - - - -- 2.49.1 From 22d6d5d3d7d5039895bc082a909ca96cfaa14465 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 01:15:17 -0400 Subject: [PATCH 10/45] Added a function to allow users to change the noisegate threshold --- NoiseGatev2.py | 8 ++++---- bot.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/NoiseGatev2.py b/NoiseGatev2.py index 9655a6a..9a35957 100644 --- a/NoiseGatev2.py +++ b/NoiseGatev2.py @@ -4,7 +4,6 @@ import pyaudio import discord import numpy -THRESHOLD = 50 voice_connection = None @@ -108,10 +107,11 @@ class AudioStream: class NoiseGate(AudioStream): - def __init__(self, _voice_connection, **kwargs): + def __init__(self, _voice_connection, _noise_gate_threshold: int = 50, **kwargs): super(NoiseGate, self).__init__(_init_on_startup=True, **kwargs) global voice_connection voice_connection = _voice_connection + self.THRESHOLD = _noise_gate_threshold self.NGStream = NoiseGateStream(self) def run(self) -> None: @@ -141,10 +141,10 @@ class NoiseGateStream(discord.AudioSource): if buffer_rms > 0: buffer_decibel = 20 * math.log10(buffer_rms) - if self.process_set_count % 25 == 0: + if self.process_set_count % 10 == 0: print(f"{buffer_decibel} db") - if buffer_decibel >= THRESHOLD: + if buffer_decibel >= self.stream.THRESHOLD: self.NG_fadeout_count = self.NG_fadeout self.process_set_count += 1 diff --git a/bot.py b/bot.py index 1f080eb..dd74724 100644 --- a/bot.py +++ b/bot.py @@ -156,6 +156,16 @@ class Bot(commands.Bot): else: await ctx.send(f"{str(member).capitalize()}, I'm not in a channel") + # Add command to change the NoiseGate threshold + @self.command(help="Use this command to change the threshold of the noisegate", + brief="Change noisegate sensitivity") + async def chngth(ctx, _threshold: int, member: discord.Member = None): + member = member or ctx.author.display_name + print(f"Change of NoiseGate threshold requested by {member}") + await ctx.send(f"Ok {str(member).capitalize()}, I'm changing the threshold from " + f"{self.streamHandler.THRESHOLD} to {_threshold}") + self.streamHandler.THRESHOLD = _threshold + # Add commands for GQRX and OP25 if self.Handler in BotResources.PDB_ACCEPTABLE_HANDLERS.keys(): # Command to display the current config -- 2.49.1 From cf79050b9640488b322d54b8494438729651c286 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 01:16:53 -0400 Subject: [PATCH 11/45] Possible fix for Nonetype error on Greada --- NoiseGatev2.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NoiseGatev2.py b/NoiseGatev2.py index 9a35957..32975cf 100644 --- a/NoiseGatev2.py +++ b/NoiseGatev2.py @@ -147,16 +147,16 @@ class NoiseGateStream(discord.AudioSource): if buffer_decibel >= self.stream.THRESHOLD: self.NG_fadeout_count = self.NG_fadeout self.process_set_count += 1 - - return bytes(curr_buffer) + if curr_buffer: + return bytes(curr_buffer) else: if self.NG_fadeout_count > 0: self.NG_fadeout_count -= 1 print(f"Frames in fadeout remaining: {self.NG_fadeout_count}") self.process_set_count += 1 - - return bytes(curr_buffer) + if curr_buffer: + return bytes(curr_buffer) except OSError as e: pass -- 2.49.1 From c1084deadff509286bd8c3e2666bc764f8ee4adc Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 01:24:36 -0400 Subject: [PATCH 12/45] Update requirements from Dan's Update --- requirements.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 68e54f9..45d8f2e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,6 @@ discord~=1.7.3 -sounddevice~=0.4.3 -pynacl~=1.5.0 +numpy==1.22.3 +scipy==1.8.0 +matplotlib~=3.5.1 +pyrtlsdr~=0.2.92 +PyAudio~=0.2.11 -- 2.49.1 From f94a900c440af28d61a507b4cd4231890b5162ce Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 14:43:33 -0400 Subject: [PATCH 13/45] Added profile commands for the bot --- BotResources.py | 2 ++ NoiseGatev2.py | 3 ++- bot.py | 36 ++++++++++++++++++++++++++---------- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/BotResources.py b/BotResources.py index 5761c8c..17939b4 100644 --- a/BotResources.py +++ b/BotResources.py @@ -10,6 +10,8 @@ PDB_ACCEPTABLE_HANDLERS = {'gqrx': { }} PDB_KNOWN_BOT_IDS = {756327271597473863: "Greada", 915064996994633729: "Jorn", 943742040255115304: "Brent"} +DEFAULT_NOISEGATE_THRESHOLD = 50 + def check_if_config_exists(): if exists('./config.ini'): diff --git a/NoiseGatev2.py b/NoiseGatev2.py index 32975cf..c6f5407 100644 --- a/NoiseGatev2.py +++ b/NoiseGatev2.py @@ -3,6 +3,7 @@ import math import pyaudio import discord import numpy +from BotResources import DEFAULT_NOISEGATE_THRESHOLD voice_connection = None @@ -107,7 +108,7 @@ class AudioStream: class NoiseGate(AudioStream): - def __init__(self, _voice_connection, _noise_gate_threshold: int = 50, **kwargs): + def __init__(self, _voice_connection, _noise_gate_threshold: int = DEFAULT_NOISEGATE_THRESHOLD, **kwargs): super(NoiseGate, self).__init__(_init_on_startup=True, **kwargs) global voice_connection voice_connection = _voice_connection diff --git a/bot.py b/bot.py index dd74724..9cff56c 100644 --- a/bot.py +++ b/bot.py @@ -42,6 +42,7 @@ class Bot(commands.Bot): self.freq = "104700000" self.mode = "wfm" self.squelch = 0 + self.noisegate_sensitivity = BotResources.DEFAULT_NOISEGATE_THRESHOLD # Init SDR Variables self.system_os_type = None @@ -102,7 +103,8 @@ class Bot(commands.Bot): # Create an audio stream from selected device print("Starting noisegate/stream handler") self.streamHandler = NoiseGatev2.NoiseGate(_input_device_index=self.DEVICE_ID, - _voice_connection=voice_connection) + _voice_connection=voice_connection, + _noise_gate_threshold=self.noisegate_sensitivity) # Start the audio stream self.streamHandler.run() @@ -165,6 +167,8 @@ class Bot(commands.Bot): await ctx.send(f"Ok {str(member).capitalize()}, I'm changing the threshold from " f"{self.streamHandler.THRESHOLD} to {_threshold}") self.streamHandler.THRESHOLD = _threshold + if self.sdr_started: + await self.set_activity() # Add commands for GQRX and OP25 if self.Handler in BotResources.PDB_ACCEPTABLE_HANDLERS.keys(): @@ -461,13 +465,14 @@ class Bot(commands.Bot): await self.change_presence(activity=discord.Game(name=f"@ me"), status=discord.Status.idle) # Save the current radio settings as a profile - async def save_radio_config(self, profile_name: str): + async def save_radio_config(self, _profile_name: str): + print(f"Saving profile {_profile_name}") config = configparser.SafeConfigParser() if os.path.exists('./profiles.ini'): config.read('./profiles.ini') - profile_name = str(profile_name).upper() + profile_name = str(_profile_name).upper() if not config.has_section(str(profile_name)): config.add_section(str(profile_name)) @@ -475,6 +480,7 @@ class Bot(commands.Bot): config[str(profile_name)]['Frequency'] = self.freq config[str(profile_name)]['Mode'] = self.mode config[str(profile_name)]['Squelch'] = str(self.squelch) + config[str(profile_name)]['Noisegate Sensitivity'] = str(self.noisegate_sensitivity) with open('./profiles.ini', 'w+') as config_file: config.write(config_file) @@ -487,6 +493,7 @@ class Bot(commands.Bot): # Load a saved profile into the current settings async def load_radio_config(self, profile_name): + print(f"Loading profile {profile_name}") config = configparser.ConfigParser() if os.path.exists('./profiles.ini'): config.read('./profiles.ini') @@ -495,6 +502,13 @@ class Bot(commands.Bot): self.freq = config[self.profile_name]['Frequency'] self.mode = config[self.profile_name]['Mode'] self.squelch = float(config[self.profile_name]['Squelch']) + try: + self.noisegate_sensitivity = int(config[self.profile_name]['Noisegate Sensitivity']) + except NameError as err: + print(f"Config does not contain a 'noisegate sensitivity' value, " + f"creating one now with the default value: {BotResources.DEFAULT_NOISEGATE_THRESHOLD}") + self.noisegate_sensitivity = BotResources.DEFAULT_NOISEGATE_THRESHOLD + await self.save_radio_config(self.profile_name) if self.sdr_started: self.start_sdr() @@ -510,10 +524,11 @@ class Bot(commands.Bot): message_body = "" if self.profile_name: message_body += f"Profile Name: {str(self.profile_name).upper()}\n" - message_body += f"Frequency: {self.freq}\n" \ - f"Mode: {str(self.mode).upper()}\n" + message_body += f"\tMode:\t\t\t\t\t{self.mode}\n" \ + f"\tFrequency:\t\t\t{self.freq}\n" \ + f"\tNoisegate Sensitivity:\t{self.noisegate_sensitivity}" if self.squelch: - message_body += f"Squelch: {self.squelch}" + message_body += f"\tSquelch:\t\t\t\t{self.squelch}" return message_body @@ -523,9 +538,10 @@ class Bot(commands.Bot): if os.path.exists('./profiles.ini'): config.read('./profiles.ini') for section in config.sections(): - message_body += f"\n{section}:\n" \ - f"\tMode:\t\t\t\t{config[section]['Mode']}\n" \ - f"\tFrequency:\t\t{config[section]['Frequency']}\n" \ - f"\tSquelch:\t\t\t{config[section]['Squelch']}\n" + message_body += f"\nProfile Name: {section}:\n" \ + f"\tMode:\t\t\t\t\t{config[section]['Mode']}\n" \ + f"\tFrequency:\t\t\t{config[section]['Frequency']}\n" \ + f"\tNoisegate Sensitivity:\t{config[section]['Noisegate Sensitivity']}" \ + f"\tSquelch:\t\t\t\t{config[section]['Squelch']}\n" return message_body -- 2.49.1 From 404ddfc77368ee622743a34d40d3e4aabdbf7063 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 04:37:29 -0400 Subject: [PATCH 14/45] Updated p25 opening --- op25Handler.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index 0e39891..0d0412e 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -51,22 +51,21 @@ class OP25Handler(threading.Thread): if self.OP25Proc is not None: self.close_op25() + p25_kwargs = ["./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", + f"{self.Frequency}e6", "-X", "-2"] + p25_stdout = subprocess.DEVNULL + p25_stderr = subprocess.STDOUT + print(f"Starting OP25") - + # Change the interpreter's working directory (idr why) cwd = os.getcwd() - os.chdir(self.OP25Dir) if self.HTTP_ENABLED: - self.OP25Proc = subprocess.Popen([f"./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", - "200000", "-o", "25600", "-U", "-f", f"{self.Frequency}e6", "-X", "-2", - "-l" "http:0.0.0.0:8080"], shell=False, stdout=subprocess.DEVNULL, - stderr=subprocess.STDOUT) + p25_kwargs.append(["-l", "http:0.0.0.0:8080"]) + p25_stdout = subprocess.STDOUT - else: - self.OP25Proc = subprocess.Popen([f"./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", - "200000", "-o", "25600", "-U", "-f", f"{self.Frequency}e6", "-X", "-2"], - shell=False, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) + self.OP25Proc = subprocess.Popen(p25_kwargs, shell=False, stdout=p25_stdout, stderr=p25_stderr) os.chdir(cwd) -- 2.49.1 From 9986eadaafb4dd40f78242f0c35098293ecbfbed Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 05:11:49 -0400 Subject: [PATCH 15/45] popen needs string? --- op25Handler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index 0d0412e..cd10c66 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -51,8 +51,8 @@ class OP25Handler(threading.Thread): if self.OP25Proc is not None: self.close_op25() - p25_kwargs = ["./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", - f"{self.Frequency}e6", "-X", "-2"] + p25_kwargs = "./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f",\ + f"{self.Frequency}e6", "-X", "-2" p25_stdout = subprocess.DEVNULL p25_stderr = subprocess.STDOUT @@ -62,7 +62,7 @@ class OP25Handler(threading.Thread): os.chdir(self.OP25Dir) if self.HTTP_ENABLED: - p25_kwargs.append(["-l", "http:0.0.0.0:8080"]) + p25_kwargs += "-l", "http:0.0.0.0:8080" p25_stdout = subprocess.STDOUT self.OP25Proc = subprocess.Popen(p25_kwargs, shell=False, stdout=p25_stdout, stderr=p25_stderr) -- 2.49.1 From f68e794d02a9949422acf3a8630553969bd675c5 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 05:17:03 -0400 Subject: [PATCH 16/45] popen needs string? --- op25Handler.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index cd10c66..a000767 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -51,8 +51,11 @@ class OP25Handler(threading.Thread): if self.OP25Proc is not None: self.close_op25() - p25_kwargs = "./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f",\ - f"{self.Frequency}e6", "-X", "-2" + #p25_kwargs = ["./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", + # f"{self.Frequency}e6", "-X", "-2"] + + p25_kwargs = f"./rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" + p25_stdout = subprocess.DEVNULL p25_stderr = subprocess.STDOUT @@ -62,7 +65,7 @@ class OP25Handler(threading.Thread): os.chdir(self.OP25Dir) if self.HTTP_ENABLED: - p25_kwargs += "-l", "http:0.0.0.0:8080" + p25_kwargs += "-l http:0.0.0.0:8080" p25_stdout = subprocess.STDOUT self.OP25Proc = subprocess.Popen(p25_kwargs, shell=False, stdout=p25_stdout, stderr=p25_stderr) -- 2.49.1 From 7d161baeda2e861e5a28958459b84afbba0c4d37 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 05:18:23 -0400 Subject: [PATCH 17/45] no space in debug emendation --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index a000767..304d6bf 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -65,7 +65,7 @@ class OP25Handler(threading.Thread): os.chdir(self.OP25Dir) if self.HTTP_ENABLED: - p25_kwargs += "-l http:0.0.0.0:8080" + p25_kwargs += " -l http:0.0.0.0:8080" p25_stdout = subprocess.STDOUT self.OP25Proc = subprocess.Popen(p25_kwargs, shell=False, stdout=p25_stdout, stderr=p25_stderr) -- 2.49.1 From bbe461255abb6d08e80fef2af38ea77cc23a0da1 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 05:20:00 -0400 Subject: [PATCH 18/45] idk --- op25Handler.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index 304d6bf..7adafb6 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -54,7 +54,7 @@ class OP25Handler(threading.Thread): #p25_kwargs = ["./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", # f"{self.Frequency}e6", "-X", "-2"] - p25_kwargs = f"./rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" + p25_kwargs = f"{self.OP25Dir}rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" p25_stdout = subprocess.DEVNULL p25_stderr = subprocess.STDOUT @@ -68,6 +68,8 @@ class OP25Handler(threading.Thread): p25_kwargs += " -l http:0.0.0.0:8080" p25_stdout = subprocess.STDOUT + print(p25_kwargs) + self.OP25Proc = subprocess.Popen(p25_kwargs, shell=False, stdout=p25_stdout, stderr=p25_stderr) os.chdir(cwd) -- 2.49.1 From 61f113c47551f1aebc4a704612bf3fea309ac339 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 12:49:08 -0400 Subject: [PATCH 19/45] Using a list with extend instead of append --- op25Handler.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index 7adafb6..c5ae6ab 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -51,10 +51,10 @@ class OP25Handler(threading.Thread): if self.OP25Proc is not None: self.close_op25() - #p25_kwargs = ["./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", - # f"{self.Frequency}e6", "-X", "-2"] + p25_kwargs = ["./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", + f"{self.Frequency}e6", "-X", "-2"] - p25_kwargs = f"{self.OP25Dir}rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" + #p25_kwargs = f"{self.OP25Dir}/rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" p25_stdout = subprocess.DEVNULL p25_stderr = subprocess.STDOUT @@ -65,7 +65,8 @@ class OP25Handler(threading.Thread): os.chdir(self.OP25Dir) if self.HTTP_ENABLED: - p25_kwargs += " -l http:0.0.0.0:8080" + p25_kwargs.extend(["-l", "http:0.0.0.0:8080"]) + #p25_kwargs += " -l http:0.0.0.0:8080" p25_stdout = subprocess.STDOUT print(p25_kwargs) -- 2.49.1 From 492026ed8c1566ce345be8a6363c398ad0b5480e Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:00:31 -0400 Subject: [PATCH 20/45] Using a list with extend instead of append --- op25Handler.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index c5ae6ab..26079cb 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -51,29 +51,30 @@ class OP25Handler(threading.Thread): if self.OP25Proc is not None: self.close_op25() - p25_kwargs = ["./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", + p25_kwargs = [f"{self.OP25Dir}./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", f"{self.Frequency}e6", "-X", "-2"] #p25_kwargs = f"{self.OP25Dir}/rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" - p25_stdout = subprocess.DEVNULL - p25_stderr = subprocess.STDOUT + #p25_stdout = subprocess.DEVNULL + #p25_stderr = subprocess.STDOUT print(f"Starting OP25") # Change the interpreter's working directory (idr why) - cwd = os.getcwd() - os.chdir(self.OP25Dir) + #cwd = os.getcwd() + #os.chdir(self.OP25Dir) if self.HTTP_ENABLED: p25_kwargs.extend(["-l", "http:0.0.0.0:8080"]) #p25_kwargs += " -l http:0.0.0.0:8080" - p25_stdout = subprocess.STDOUT + #p25_stdout = subprocess.STDOUT print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, shell=False, stdout=p25_stdout, stderr=p25_stderr) + self.OP25Proc = subprocess.Popen(p25_kwargs, shell=False, stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, + cwd=self.OP25Dir) - os.chdir(cwd) + #os.chdir(cwd) def close_op25(self): print(f"Closing OP25") -- 2.49.1 From e5b33595716e4586912e649c8c047bdffe2875eb Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:03:00 -0400 Subject: [PATCH 21/45] Using a list with extend instead of append --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index 26079cb..e846008 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -51,7 +51,7 @@ class OP25Handler(threading.Thread): if self.OP25Proc is not None: self.close_op25() - p25_kwargs = [f"{self.OP25Dir}./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", + p25_kwargs = [f"{self.OP25Dir}/rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", f"{self.Frequency}e6", "-X", "-2"] #p25_kwargs = f"{self.OP25Dir}/rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" -- 2.49.1 From c03521de7f5de13628908fc496d869e37f736d79 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:12:25 -0400 Subject: [PATCH 22/45] Using a list with extend instead of append --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index e846008..9468833 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -71,7 +71,7 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, shell=False, stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, + self.OP25Proc = subprocess.Popen(p25_kwargs, shell=False, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From 6049af3a251c0248de41a61f9b267ba008e3389a Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:19:29 -0400 Subject: [PATCH 23/45] Trying to use stdout/stderr --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index 9468833..0b8c774 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -71,7 +71,7 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, shell=False, + self.OP25Proc = subprocess.Popen(p25_kwargs, shell=True, stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From 5fe98bfe0ec070f9bcb029b0e0d4a5113708d055 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:29:15 -0400 Subject: [PATCH 24/45] Trying to use stdin, executable and shell --- op25Handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index 0b8c774..9eba71a 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -71,8 +71,8 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, shell=True, stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, - cwd=self.OP25Dir) + self.OP25Proc = subprocess.Popen(p25_kwargs, shell=True, executable="/usr/bin/python3", stdin=None, + stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From 7cca55a836a51f88a1a9c18b517b31a82ffc1b75 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:32:49 -0400 Subject: [PATCH 25/45] Trying to use pipe --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index 9eba71a..e4230d6 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -71,7 +71,7 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, shell=True, executable="/usr/bin/python3", stdin=None, + self.OP25Proc = subprocess.Popen(p25_kwargs, shell=True, executable="/usr/bin/python3", stdin=subprocess.PIPE, stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From dd9643363b34a6092f25814add6dcec2e7ffff75 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:40:00 -0400 Subject: [PATCH 26/45] idk --- op25Handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index e4230d6..f155116 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -71,8 +71,8 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, shell=True, executable="/usr/bin/python3", stdin=subprocess.PIPE, - stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, cwd=self.OP25Dir) + self.OP25Proc = subprocess.Popen(p25_kwargs, executable="/usr/bin/python3", shell=False, + stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From 8c7075b76c41f52647fac787f00b356e8d954a68 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:43:52 -0400 Subject: [PATCH 27/45] idk --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index f155116..ceb99f4 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -71,7 +71,7 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, executable="/usr/bin/python3", shell=False, + self.OP25Proc = subprocess.Popen(p25_kwargs, executable="/usr/bin/python3", shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From 0c53e58fab67a58d6a35dda5b8fcebaf0e6a460f Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:46:44 -0400 Subject: [PATCH 28/45] idk --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index ceb99f4..c79b6e5 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -72,7 +72,7 @@ class OP25Handler(threading.Thread): print(p25_kwargs) self.OP25Proc = subprocess.Popen(p25_kwargs, executable="/usr/bin/python3", shell=True, - stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, cwd=self.OP25Dir) + stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From 5d7a3b2d0bbd8979fef0c8d99fba33d2766b0424 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:48:07 -0400 Subject: [PATCH 29/45] idk --- op25Handler.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index c79b6e5..ca2e523 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -71,8 +71,7 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, executable="/usr/bin/python3", shell=True, - stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, cwd=self.OP25Dir) + self.OP25Proc = subprocess.Popen(p25_kwargs, executable="/usr/bin/python3", shell=True, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From f64a3dc51768f642106a3fe6749f36d906531ff1 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:49:02 -0400 Subject: [PATCH 30/45] idk --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index ca2e523..53c1270 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -51,7 +51,7 @@ class OP25Handler(threading.Thread): if self.OP25Proc is not None: self.close_op25() - p25_kwargs = [f"{self.OP25Dir}/rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", + p25_kwargs = [f"./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", f"{self.Frequency}e6", "-X", "-2"] #p25_kwargs = f"{self.OP25Dir}/rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" -- 2.49.1 From 97aed314ba5ebdaa232f49737a8eef6cfad22c5a Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:50:24 -0400 Subject: [PATCH 31/45] idk --- op25Handler.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index 53c1270..6e489e4 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -51,7 +51,7 @@ class OP25Handler(threading.Thread): if self.OP25Proc is not None: self.close_op25() - p25_kwargs = [f"./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", + p25_kwargs = [f"{self.OP25Dir}/rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", f"{self.Frequency}e6", "-X", "-2"] #p25_kwargs = f"{self.OP25Dir}/rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" @@ -71,7 +71,8 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, executable="/usr/bin/python3", shell=True, cwd=self.OP25Dir) + self.OP25Proc = subprocess.Popen(p25_kwargs, executable="/usr/bin/python3", shell=False, + stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From 831c19e7e1d9417cfe6a0e148ea6b4a2eae8f767 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 13:52:37 -0400 Subject: [PATCH 32/45] idk --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index 6e489e4..56c8059 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -51,7 +51,7 @@ class OP25Handler(threading.Thread): if self.OP25Proc is not None: self.close_op25() - p25_kwargs = [f"{self.OP25Dir}/rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", + p25_kwargs = [f"rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", f"{self.Frequency}e6", "-X", "-2"] #p25_kwargs = f"{self.OP25Dir}/rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" -- 2.49.1 From f90c84184a59a14a9f22078b0ef741fcdc6a4fef Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 14:01:49 -0400 Subject: [PATCH 33/45] idk --- op25Handler.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index 56c8059..bbca7c3 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -1,3 +1,4 @@ +import shutil import threading import subprocess import asyncio @@ -9,6 +10,7 @@ class OP25Handler(threading.Thread): def __init__(self): super().__init__() self.OP25Dir: str = "/home/pi/op25/op25/gr-op25_repeater/apps" + self.OP25EXE: str = shutil.which("/home/pi/op25/op25/gr-op25_repeater/apps/rx.py") self.OP25Proc = None self.Frequency = None @@ -71,8 +73,8 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, executable="/usr/bin/python3", shell=False, - stdout=subprocess.STDOUT, stderr=subprocess.STDOUT, cwd=self.OP25Dir) + self.OP25Proc = subprocess.Popen(p25_kwargs, executable=self.OP25EXE, shell=True, stdout=subprocess.STDOUT, + stderr=subprocess.STDOUT, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From 4eb73c38328fb804b0b67b0459a5988e3826d416 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 14:03:40 -0400 Subject: [PATCH 34/45] idk --- op25Handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index bbca7c3..6ff4ada 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -73,8 +73,8 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, executable=self.OP25EXE, shell=True, stdout=subprocess.STDOUT, - stderr=subprocess.STDOUT, cwd=self.OP25Dir) + self.OP25Proc = subprocess.Popen(p25_kwargs, executable=self.OP25EXE, shell=True, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From 79c651be308f46dcf775b13a682ffa393ebd6db0 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 14:06:36 -0400 Subject: [PATCH 35/45] idk --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index 6ff4ada..b8007ac 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -53,7 +53,7 @@ class OP25Handler(threading.Thread): if self.OP25Proc is not None: self.close_op25() - p25_kwargs = [f"rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", + p25_kwargs = [f"./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", f"{self.Frequency}e6", "-X", "-2"] #p25_kwargs = f"{self.OP25Dir}/rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" -- 2.49.1 From 69c7d4d548a84313833d1a89a90053e8f9a62be1 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 14:08:53 -0400 Subject: [PATCH 36/45] idk --- op25Handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op25Handler.py b/op25Handler.py index b8007ac..86d85b3 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -73,7 +73,7 @@ class OP25Handler(threading.Thread): print(p25_kwargs) - self.OP25Proc = subprocess.Popen(p25_kwargs, executable=self.OP25EXE, shell=True, stdin=subprocess.PIPE, + self.OP25Proc = subprocess.Popen(p25_kwargs, executable=self.OP25EXE, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.OP25Dir) #os.chdir(cwd) -- 2.49.1 From 05e81aea1dbf7b5520daf415f5485c7e302a905f Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 14:18:16 -0400 Subject: [PATCH 37/45] Better output --- op25Handler.py | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/op25Handler.py b/op25Handler.py index 86d85b3..b78fb0b 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -56,28 +56,16 @@ class OP25Handler(threading.Thread): p25_kwargs = [f"./rx.py", "--args", "rtl", "-N", "LNA:49", "-s", "200000", "-o", "25600", "-U", "-f", f"{self.Frequency}e6", "-X", "-2"] - #p25_kwargs = f"{self.OP25Dir}/rx.py --args rtl -N LNA:49 -s 200000 -o 25600 -U -f {self.Frequency}e6 -X -2" - - #p25_stdout = subprocess.DEVNULL - #p25_stderr = subprocess.STDOUT - print(f"Starting OP25") # Change the interpreter's working directory (idr why) - #cwd = os.getcwd() - #os.chdir(self.OP25Dir) - if self.HTTP_ENABLED: p25_kwargs.extend(["-l", "http:0.0.0.0:8080"]) - #p25_kwargs += " -l http:0.0.0.0:8080" - #p25_stdout = subprocess.STDOUT - print(p25_kwargs) + print(f"OP25 Keyword Args: {p25_kwargs}") self.OP25Proc = subprocess.Popen(p25_kwargs, executable=self.OP25EXE, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.OP25Dir) - #os.chdir(cwd) - def close_op25(self): print(f"Closing OP25") try: -- 2.49.1 From 0d32d3fa7ec2522bbc0d525a5a7b02d22d3f8dfc Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Thu, 17 Mar 2022 22:41:37 -0400 Subject: [PATCH 38/45] rebase master into NoiseGateV2 --- NoiseGate-v2.py | 130 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 NoiseGate-v2.py diff --git a/NoiseGate-v2.py b/NoiseGate-v2.py new file mode 100644 index 0000000..7381b52 --- /dev/null +++ b/NoiseGate-v2.py @@ -0,0 +1,130 @@ +import pyaudio +import struct +import numpy +import time +from threading import Thread + +sound_buffer = [] + + +class AudioStream(Thread): + def __init__(self, _channels: int = 1, _sample_rate: int = 48000, _frames_per_buffer: int = 2048, + _input_device_index: int = None, _output_device_index: int = None, _input: bool = True, + _output: bool = True): + super(AudioStream, self).__init__() + self.paInstance_kwargs = { + 'format': pyaudio.paFloat32, + 'channels': _channels, + 'rate': _sample_rate, + 'input': _input, + 'output': _output, + 'frames_per_buffer': _frames_per_buffer, + 'stream_callback': callback + } + + if _input_device_index: + if _input: + self.paInstance_kwargs['input_device_index'] = _input_device_index + else: + print(f"[AudioStream.__init__]:\tInput was not enabled." + f" Reinitialize with '_input=True'") + + if _output_device_index: + if _output: + self.paInstance_kwargs['output_device_index'] = _output_device_index + else: + print(f"[AudioStream.__init__]:\tOutput was not enabled." + f" Reinitialize with '_output=True'") + + # Init PyAudio instance + self.paInstance = pyaudio.PyAudio() + + # Define and initialize stream object if we have been passed a device ID (pyaudio.open) + self.stream = None + if _output_device_index and _input_device_index: + self.init_stream() + + # temp section + + def init_stream(self, _new_output_device_index: int = None, _new_input_device_index: int = None): + # Check what device was asked to be changed (or set) + if _new_input_device_index: + if self.paInstance_kwargs['input']: + self.paInstance_kwargs['input_device_index'] = _new_input_device_index + else: + print(f"[AudioStream.init_stream]:\tInput was not enabled when initialized." + f" Reinitialize with '_input=True'") + + if _new_output_device_index: + if self.paInstance_kwargs['output']: + self.paInstance_kwargs['output_device_index'] = _new_output_device_index + else: + print(f"[AudioStream.init_stream]:\tOutput was not enabled when initialized." + f" Reinitialize with '_output=True'") + + self.close_if_open() + + # Reopen the stream + self.stream = self.paInstance.open(**self.paInstance_kwargs) + + def close_if_open(self): + # Stop the stream if it is started + if self.stream: + if self.stream.is_active(): + self.stream.stop_stream() + self.stream.close() + print(f"[ReopenStream.close_if_open]:\t Stream was open; It was closed.") + + def list_devices(self, _show_input_devices: bool = True, _show_output_devices: bool = True): + info = self.paInstance.get_host_api_info_by_index(0) + numdevices = info.get('deviceCount') + + for i in range(0, numdevices): + if (self.paInstance.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0: + if _show_input_devices: + print("Input Device id ", i, " - ", + self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name')) + + if (self.paInstance.get_device_info_by_host_api_device_index(0, i).get('maxOutputChannels')) > 0: + if _show_output_devices: + print("Output Device id ", i, " - ", + self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name')) + + +class NoiseGate(AudioStream): + def __init__(self, **kwargs): + super().__init__(**kwargs) + + def run(self) -> None: + # Start the audio stream + self.stream.start_stream() + + global sound_buffer + # While the stream is running, display the stream buffer in floats? + while self.stream.is_active(): + if len(sound_buffer) > 0: + for buffer in sound_buffer: + volume_normalization = numpy.linalg.norm(numpy.fromstring(buffer)) * 10 + print(str(float(volume_normalization))) + + self.stream.stop_stream() + self.stream.close() + + self.paInstance.terminate() + + +def callback(in_data, frame_count, time_info, status): + global sound_buffer + + sound_buffer.append(in_data) + + return in_data, pyaudio.paContinue + + +if __name__ == '__main__': + input_index = int(input("Input:\t")) + output_index = int(input("Output:\t")) + + ng = NoiseGate(_input_device_index=input_index, _output_device_index=output_index) + + ng.start() -- 2.49.1 From 54e3a3a116921c4390725b81d4b57bf360d52cb1 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 14:50:42 -0400 Subject: [PATCH 39/45] Remove dupe file --- NoiseGate-v2.py | 130 ------------------------------------------------ 1 file changed, 130 deletions(-) delete mode 100644 NoiseGate-v2.py diff --git a/NoiseGate-v2.py b/NoiseGate-v2.py deleted file mode 100644 index 7381b52..0000000 --- a/NoiseGate-v2.py +++ /dev/null @@ -1,130 +0,0 @@ -import pyaudio -import struct -import numpy -import time -from threading import Thread - -sound_buffer = [] - - -class AudioStream(Thread): - def __init__(self, _channels: int = 1, _sample_rate: int = 48000, _frames_per_buffer: int = 2048, - _input_device_index: int = None, _output_device_index: int = None, _input: bool = True, - _output: bool = True): - super(AudioStream, self).__init__() - self.paInstance_kwargs = { - 'format': pyaudio.paFloat32, - 'channels': _channels, - 'rate': _sample_rate, - 'input': _input, - 'output': _output, - 'frames_per_buffer': _frames_per_buffer, - 'stream_callback': callback - } - - if _input_device_index: - if _input: - self.paInstance_kwargs['input_device_index'] = _input_device_index - else: - print(f"[AudioStream.__init__]:\tInput was not enabled." - f" Reinitialize with '_input=True'") - - if _output_device_index: - if _output: - self.paInstance_kwargs['output_device_index'] = _output_device_index - else: - print(f"[AudioStream.__init__]:\tOutput was not enabled." - f" Reinitialize with '_output=True'") - - # Init PyAudio instance - self.paInstance = pyaudio.PyAudio() - - # Define and initialize stream object if we have been passed a device ID (pyaudio.open) - self.stream = None - if _output_device_index and _input_device_index: - self.init_stream() - - # temp section - - def init_stream(self, _new_output_device_index: int = None, _new_input_device_index: int = None): - # Check what device was asked to be changed (or set) - if _new_input_device_index: - if self.paInstance_kwargs['input']: - self.paInstance_kwargs['input_device_index'] = _new_input_device_index - else: - print(f"[AudioStream.init_stream]:\tInput was not enabled when initialized." - f" Reinitialize with '_input=True'") - - if _new_output_device_index: - if self.paInstance_kwargs['output']: - self.paInstance_kwargs['output_device_index'] = _new_output_device_index - else: - print(f"[AudioStream.init_stream]:\tOutput was not enabled when initialized." - f" Reinitialize with '_output=True'") - - self.close_if_open() - - # Reopen the stream - self.stream = self.paInstance.open(**self.paInstance_kwargs) - - def close_if_open(self): - # Stop the stream if it is started - if self.stream: - if self.stream.is_active(): - self.stream.stop_stream() - self.stream.close() - print(f"[ReopenStream.close_if_open]:\t Stream was open; It was closed.") - - def list_devices(self, _show_input_devices: bool = True, _show_output_devices: bool = True): - info = self.paInstance.get_host_api_info_by_index(0) - numdevices = info.get('deviceCount') - - for i in range(0, numdevices): - if (self.paInstance.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0: - if _show_input_devices: - print("Input Device id ", i, " - ", - self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name')) - - if (self.paInstance.get_device_info_by_host_api_device_index(0, i).get('maxOutputChannels')) > 0: - if _show_output_devices: - print("Output Device id ", i, " - ", - self.paInstance.get_device_info_by_host_api_device_index(0, i).get('name')) - - -class NoiseGate(AudioStream): - def __init__(self, **kwargs): - super().__init__(**kwargs) - - def run(self) -> None: - # Start the audio stream - self.stream.start_stream() - - global sound_buffer - # While the stream is running, display the stream buffer in floats? - while self.stream.is_active(): - if len(sound_buffer) > 0: - for buffer in sound_buffer: - volume_normalization = numpy.linalg.norm(numpy.fromstring(buffer)) * 10 - print(str(float(volume_normalization))) - - self.stream.stop_stream() - self.stream.close() - - self.paInstance.terminate() - - -def callback(in_data, frame_count, time_info, status): - global sound_buffer - - sound_buffer.append(in_data) - - return in_data, pyaudio.paContinue - - -if __name__ == '__main__': - input_index = int(input("Input:\t")) - output_index = int(input("Output:\t")) - - ng = NoiseGate(_input_device_index=input_index, _output_device_index=output_index) - - ng.start() -- 2.49.1 From 3a2d9531f9b29430d2913d20c74aabdfab4c121f Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 14:55:11 -0400 Subject: [PATCH 40/45] Removing circular import --- NoiseGatev2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/NoiseGatev2.py b/NoiseGatev2.py index c6f5407..c0f4bfd 100644 --- a/NoiseGatev2.py +++ b/NoiseGatev2.py @@ -3,7 +3,6 @@ import math import pyaudio import discord import numpy -from BotResources import DEFAULT_NOISEGATE_THRESHOLD voice_connection = None @@ -108,7 +107,7 @@ class AudioStream: class NoiseGate(AudioStream): - def __init__(self, _voice_connection, _noise_gate_threshold: int = DEFAULT_NOISEGATE_THRESHOLD, **kwargs): + def __init__(self, _voice_connection, _noise_gate_threshold: int, **kwargs): super(NoiseGate, self).__init__(_init_on_startup=True, **kwargs) global voice_connection voice_connection = _voice_connection -- 2.49.1 From 1a705c2b6c87476d79d50c0664d4280f9699f2b8 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 14:56:56 -0400 Subject: [PATCH 41/45] KeyError instead of NameError ~507 bot.py --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 9cff56c..a5e6430 100644 --- a/bot.py +++ b/bot.py @@ -504,7 +504,7 @@ class Bot(commands.Bot): self.squelch = float(config[self.profile_name]['Squelch']) try: self.noisegate_sensitivity = int(config[self.profile_name]['Noisegate Sensitivity']) - except NameError as err: + except KeyError as err: print(f"Config does not contain a 'noisegate sensitivity' value, " f"creating one now with the default value: {BotResources.DEFAULT_NOISEGATE_THRESHOLD}") self.noisegate_sensitivity = BotResources.DEFAULT_NOISEGATE_THRESHOLD -- 2.49.1 From 83c29717429dac65bca3cb5aef029db1f3ba2d28 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 15:00:58 -0400 Subject: [PATCH 42/45] No spaces in profiles --- bot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index a5e6430..c428758 100644 --- a/bot.py +++ b/bot.py @@ -480,7 +480,7 @@ class Bot(commands.Bot): config[str(profile_name)]['Frequency'] = self.freq config[str(profile_name)]['Mode'] = self.mode config[str(profile_name)]['Squelch'] = str(self.squelch) - config[str(profile_name)]['Noisegate Sensitivity'] = str(self.noisegate_sensitivity) + config[str(profile_name)]['Noisegate_Sensitivity'] = str(self.noisegate_sensitivity) with open('./profiles.ini', 'w+') as config_file: config.write(config_file) @@ -503,8 +503,8 @@ class Bot(commands.Bot): self.mode = config[self.profile_name]['Mode'] self.squelch = float(config[self.profile_name]['Squelch']) try: - self.noisegate_sensitivity = int(config[self.profile_name]['Noisegate Sensitivity']) - except KeyError as err: + self.noisegate_sensitivity = int(config[self.profile_name]['Noisegate_Sensitivity']) + except KeyError: print(f"Config does not contain a 'noisegate sensitivity' value, " f"creating one now with the default value: {BotResources.DEFAULT_NOISEGATE_THRESHOLD}") self.noisegate_sensitivity = BotResources.DEFAULT_NOISEGATE_THRESHOLD -- 2.49.1 From 8e191531d0b1dd768b751c26671ea087ce9254c2 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 15:03:41 -0400 Subject: [PATCH 43/45] Reads profiles without noisegate sensitivity value --- bot.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index c428758..9d92e30 100644 --- a/bot.py +++ b/bot.py @@ -540,8 +540,12 @@ class Bot(commands.Bot): for section in config.sections(): message_body += f"\nProfile Name: {section}:\n" \ f"\tMode:\t\t\t\t\t{config[section]['Mode']}\n" \ - f"\tFrequency:\t\t\t{config[section]['Frequency']}\n" \ - f"\tNoisegate Sensitivity:\t{config[section]['Noisegate Sensitivity']}" \ - f"\tSquelch:\t\t\t\t{config[section]['Squelch']}\n" + f"\tFrequency:\t\t\t{config[section]['Frequency']}\n" + try: + message_body += f"\tNoisegate Sensitivity:\t{config[section]['Noisegate Sensitivity']}" + except KeyError: + print(f"Config does not contain a 'noisegate sensitivity' value. Please load the profile") + + message_body += f"\tSquelch:\t\t\t\t{config[section]['Squelch']}\n" return message_body -- 2.49.1 From 63ca0fec63e30676a25a81fe8c4b709c4db31225 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 15:04:55 -0400 Subject: [PATCH 44/45] silly bug --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 9d92e30..012c86e 100644 --- a/bot.py +++ b/bot.py @@ -542,7 +542,7 @@ class Bot(commands.Bot): f"\tMode:\t\t\t\t\t{config[section]['Mode']}\n" \ f"\tFrequency:\t\t\t{config[section]['Frequency']}\n" try: - message_body += f"\tNoisegate Sensitivity:\t{config[section]['Noisegate Sensitivity']}" + message_body += f"\tNoisegate Sensitivity:\t{config[section]['Noisegate_Sensitivity']}" except KeyError: print(f"Config does not contain a 'noisegate sensitivity' value. Please load the profile") -- 2.49.1 From 8c5cc65a50ceceed68884a5e48ec299be334b12d Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 27 Mar 2022 15:05:46 -0400 Subject: [PATCH 45/45] no new line at the end of display profiles --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 012c86e..e30a7fd 100644 --- a/bot.py +++ b/bot.py @@ -542,7 +542,7 @@ class Bot(commands.Bot): f"\tMode:\t\t\t\t\t{config[section]['Mode']}\n" \ f"\tFrequency:\t\t\t{config[section]['Frequency']}\n" try: - message_body += f"\tNoisegate Sensitivity:\t{config[section]['Noisegate_Sensitivity']}" + message_body += f"\tNoisegate Sensitivity:\t{config[section]['Noisegate_Sensitivity']}\n" except KeyError: print(f"Config does not contain a 'noisegate sensitivity' value. Please load the profile") -- 2.49.1