diff --git a/Client/__pycache__/appcomponent.cpython-310.pyc b/Client/__pycache__/appcomponent.cpython-310.pyc
index bfe064c..2dd4eb4 100644
Binary files a/Client/__pycache__/appcomponent.cpython-310.pyc and b/Client/__pycache__/appcomponent.cpython-310.pyc differ
diff --git a/Client/client.py b/Client/client.py
index 74a63e5..932631f 100644
--- a/Client/client.py
+++ b/Client/client.py
@@ -28,7 +28,7 @@ import zmq
from pyogg import OpusDecoder
import configparser
import ctypes
-import zlib
+import lz4.frame
from utils import *
import appcomponent
@@ -40,7 +40,7 @@ class App:
self.config = configparser.ConfigParser()
self.config.read("config.ini")
self.device_name_output = self.config["audio"]["device"]
- self.buffersize = self.config["network"]["buffersize"]
+ self.buffersize = int(self.config["network"]["buffersize"])
self.working = False
self.readchannel = 1
@@ -396,7 +396,7 @@ class App:
break
try:
- decompressed_data = zlib.decompress(data)
+ decompressed_data = lz4.frame.decompress(data)
datadecoded = pickle.loads(decompressed_data)
except:
diff --git a/Server/Encoder.py b/Server/Encoder.py
index 2cff720..91a1986 100644
--- a/Server/Encoder.py
+++ b/Server/Encoder.py
@@ -14,14 +14,12 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with IDRB Project. If not, see .
"""
-
import threading
from queue import Queue
-from pyogg import OpusBufferedEncoder
-import numpy as np
import pyaudio
import RDS as _RDS
import logging
+import tools
EncoderLog = logging.getLogger("Encoder")
@@ -37,64 +35,28 @@ for i in range(p.get_device_count()):
device_index_input = dev['index']
break
-device_name_input = "Line 4 (Virtual Audio Cable)"
-device_index_input2 = 0
-for i in range(p.get_device_count()):
- dev = p.get_device_info_by_index(i)
- if dev['name'] == device_name_input:
- device_index_input2 = dev['index']
- break
-
-streaminput = p.open(format=pyaudio.paInt16, channels=2, rate=48000, input=True, input_device_index=device_index_input)
-streaminput2 = p.open(format=pyaudio.paInt16, channels=2, rate=48000, input=True, input_device_index=device_index_input2)
-
# Create a shared queue for encoded audio packets
channel1 = Queue()
channel2 = Queue()
-# Function to continuously encode audio and put it into the queue
-def encode_audio():
- encoder = OpusBufferedEncoder()
- encoder.set_application("audio")
- encoder.set_sampling_frequency(_RDS.RDS["ContentInfo"]["samplerates"])
- encoder.set_channels(_RDS.RDS["ContentInfo"]["channel"])
- encoder.set_bitrates(_RDS.RDS["ContentInfo"]["bitrate"])
- encoder.set_frame_size(60)
- encoder.set_bitrate_mode("VBR")
- encoder.set_compresion_complex(10)
+channel1option = {
+ "Bitrates": 64000,
+ "DeviceInputIndex": device_index_input
+}
- while True:
- pcm = np.frombuffer(streaminput.read(1024, exception_on_overflow=False), dtype=np.int16)
+channel2option = {
+ "Bitrates": 18000,
+ "InputWAVFile": "./Samples/audiotest.wav"
+}
- encoded_packets = encoder.buffered_encode(memoryview(bytearray(pcm)))
- for encoded_packet, _, _ in encoded_packets:
- # Put the encoded audio into the buffer
- channel1.put(encoded_packet.tobytes())
+EncoderChannel1 = tools.AudioEncoder(_RDS.RDS, channel1option, channel1)
-def encode_audio2():
- encoder2 = OpusBufferedEncoder()
- encoder2.set_application("audio")
- encoder2.set_sampling_frequency(_RDS.RDS2["ContentInfo"]["samplerates"])
- encoder2.set_channels(_RDS.RDS2["ContentInfo"]["channel"])
- encoder2.set_bitrates(_RDS.RDS2["ContentInfo"]["bitrate"])
- encoder2.set_frame_size(60)
-
- while True:
- pcm2 = np.frombuffer(streaminput2.read(1024, exception_on_overflow=False), dtype=np.int16)
-
- encoded_packets = encoder2.buffered_encode(memoryview(bytearray(pcm2)))
- for encoded_packet, _, _ in encoded_packets:
- # Put the encoded audio into the buffer
- channel2.put(encoded_packet.tobytes())
-
- #channel2.put(pcm2.tobytes()) # if you use pcm
+EncoderChannel2 = tools.AudioEncoder(_RDS.RDS2, channel2option, channel2, "wav")
def StartEncoder():
EncoderLog.info("Starting encoder")
- audio_thread = threading.Thread(target=encode_audio)
- audio_thread2 = threading.Thread(target=encode_audio2)
- audio_thread.start()
- audio_thread2.start()
\ No newline at end of file
+ EncoderChannel1.startencoder()
+ EncoderChannel2.startencoder()
\ No newline at end of file
diff --git a/Server/RDS.py b/Server/RDS.py
index 8833964..994b62b 100644
--- a/Server/RDS.py
+++ b/Server/RDS.py
@@ -19,7 +19,7 @@ import time
from datetime import datetime
import cv2
import numpy as np
-from damp11113 import scrollTextBySteps
+from damp11113.utils import scrollTextBySteps
import threading
import Settings
import logging
@@ -96,12 +96,6 @@ RDS = {
"AS": [ # AS = Alternative Server
# can add more server here
],
- "ContentInfo": {
- "Codec": "opus",
- "bitrate": 64000,
- "channel": 2,
- "samplerates": 48000
- },
"images": {
"logo": {
"lazy": False,
@@ -145,12 +139,6 @@ RDS2 = {
"AS": [ # AS = Alternative Server
# can add more server here
],
- "ContentInfo": {
- "Codec": "Opus",
- "bitrate": 8000,
- "channel": 2,
- "samplerates": 48000
- },
"images": {
"logo": None
}
@@ -194,5 +182,5 @@ def startRDSThread():
thread.start()
thread2.start()
- thread3.start()
+ #thread3.start()
diff --git a/Server/Samples/audiotest.wav b/Server/Samples/audiotest.wav
new file mode 100644
index 0000000..b8e2ef9
Binary files /dev/null and b/Server/Samples/audiotest.wav differ
diff --git a/Server/Settings.py b/Server/Settings.py
index 0bfe478..eb35dae 100644
--- a/Server/Settings.py
+++ b/Server/Settings.py
@@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License
along with IDRB Project. If not, see .
"""
+import lz4.frame
+
# To config Muxer you need to goto server.py and find "Config Muxer"
# To config RDS you need to goto RDS.py
# To config Encoder you need to goto Encoder.py
@@ -23,7 +25,7 @@ along with IDRB Project. If not, see .
# Server Settings
protocol = "ZMQ_WS" # TCP ZMQ ZMQ_WS
server_port = ('*', 6980) # if use other protocol ZMQ please use 0.0.0.0
-compression_level = 9 # 0-9
+compression_level = lz4.frame.COMPRESSIONLEVEL_MAX
buffersize = 32 # must be int (on working it use buffersize + (buffersize/2) to standby)
# low buffersize = low delay
@@ -42,13 +44,9 @@ If you want your server to be listed publicly on ThaiSDR Directory, following th
6. copy api key
"""
-public = True
+public = False
#ServerIP = "IDRB.damp11113.xyz" # do not add protocol before ip
ServerIP = "localhost"
#ServerPort = server_port[1]
ServerPort = 6980
-<<<<<<< HEAD
-ThaiSDRkey = ""
-=======
-ThaiSDRkey = ""
->>>>>>> 53163be3dc12010715271f6020a0c07d2af720ec
+ThaiSDRkey = "1N5LURICLIN1U9QNYZ4MHJ6FNXISFXFELZAX135CFM0HSD17O2.63E60BE9EEA2339C113A15EB"
diff --git a/Server/__pycache__/Encoder.cpython-310.pyc b/Server/__pycache__/Encoder.cpython-310.pyc
index 3eaf79e..d5208db 100644
Binary files a/Server/__pycache__/Encoder.cpython-310.pyc and b/Server/__pycache__/Encoder.cpython-310.pyc differ
diff --git a/Server/__pycache__/RDS.cpython-310.pyc b/Server/__pycache__/RDS.cpython-310.pyc
index 46653df..d2cea96 100644
Binary files a/Server/__pycache__/RDS.cpython-310.pyc and b/Server/__pycache__/RDS.cpython-310.pyc differ
diff --git a/Server/__pycache__/Settings.cpython-310.pyc b/Server/__pycache__/Settings.cpython-310.pyc
index 4533904..d962345 100644
Binary files a/Server/__pycache__/Settings.cpython-310.pyc and b/Server/__pycache__/Settings.cpython-310.pyc differ
diff --git a/Server/__pycache__/tools.cpython-310.pyc b/Server/__pycache__/tools.cpython-310.pyc
new file mode 100644
index 0000000..df7695c
Binary files /dev/null and b/Server/__pycache__/tools.cpython-310.pyc differ
diff --git a/Server/server.py b/Server/server.py
index 703d29b..0635c01 100644
--- a/Server/server.py
+++ b/Server/server.py
@@ -21,9 +21,13 @@ import pickle
import threading
import zmq
import logging
-import zlib
+import lz4.frame
import queue
import math
+import os
+
+os.environ["damp11113_load_all_module"] = "NO"
+os.environ["damp11113_check_update"] = "NO"
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
ServerLog = logging.getLogger("IDRBServer")
@@ -88,8 +92,10 @@ def Muxer():
# ENC1encrypted, ENC1salt, ENC1iv = utils.encrypt_data(ENchannel1, "password")
# ENchannel1 = ENC1encrypted + b'|||||' + ENC1salt + b'|||||' + ENC1iv
-
- ENchannel2 = Encoder.channel2.get()
+ try:
+ ENchannel2 = Encoder.channel2.get()
+ except:
+ ENchannel2 = b""
content = {
"first": False,
"mainchannel": 1,
@@ -119,7 +125,7 @@ def Muxer():
}
ThaiSDRDir.content = content
- compressedcontent = zlib.compress(pickle.dumps(content), level=Settings.compression_level)
+ compressedcontent = lz4.frame.compress(pickle.dumps(content), compression_level=Settings.compression_level)
Buffer.put(compressedcontent)
diff --git a/Server/tools.py b/Server/tools.py
new file mode 100644
index 0000000..efff21e
--- /dev/null
+++ b/Server/tools.py
@@ -0,0 +1,141 @@
+"""
+This file is part of IDRB Project.
+
+IDRB Project is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+IDRB Project is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IDRB Project. If not, see .
+"""
+import socket
+import time
+from pyogg import OpusBufferedEncoder
+import numpy as np
+import pyaudio
+import wave
+import threading
+from damp11113.randoms import rannum
+
+class AudioEncoder:
+ def __init__(self, RDS: dict, option: dict, queuebuffer, audioinputtype="device", audiocodec="opus", standalone=False):
+ self.audiocodec = audiocodec.upper()
+ self.audioinput = audioinputtype.upper()
+ self.RDS = RDS
+ self.option = option
+ self.buffer = queuebuffer
+
+ self.running = False
+ self.encoder = None
+ self.standalone = standalone
+
+ self.runningthread = threading.Thread(target=self._running)
+ self.sourceinput = None
+
+ self._temp_ip = None
+ self._temp_port = None
+
+ self._temp_socket = None
+
+ def _createencoder(self):
+ self.RDS.update({
+ "ContentInfo": {
+ "Codec": self.audiocodec,
+ "bitrate": self.option.get("Bitrates", 64000),
+ "channel": self.option.get("Channel", 2),
+ "samplerates": self.option.get("SamplesRates", 48000)
+ }
+ })
+
+ if self.audiocodec == "PCM":
+ pass
+ elif self.audiocodec == "OPUS":
+ self.encoder = OpusBufferedEncoder()
+ self.encoder.set_application("audio")
+ self.encoder.set_sampling_frequency(self.option.get("SamplesRates", 48000))
+ self.encoder.set_channels(self.option.get("Channel", 2))
+ self.encoder.set_bitrates(self.option.get("Bitrates", 64000))
+ self.encoder.set_frame_size(self.option.get("opusFrameSize", 60))
+ self.encoder.set_bitrate_mode(self.option.get("BitrateMode", "VBR").upper())
+ self.encoder.set_compresion_complex(self.option.get("opusCompressionLevel", 10))
+
+ def _createaudiosource(self):
+ if self.audioinput == "DEVICE":
+ p = pyaudio.PyAudio()
+ self.sourceinput = p.open(format=pyaudio.paInt16, channels=self.option.get("Channel", 2), rate=self.option.get("SamplesRates", 48000), input=True, input_device_index=self.option.get("DeviceInputIndex", 0))
+ elif self.audioinput == "WAV":
+ file = self.option.get("InputWAVFile", "")
+ if file == "":
+ raise "No Audio wav Input Please use option 'InputWAVFile' to set wav file path"
+ self.sourceinput = wave.open(file, "rb")
+ elif self.audioinput == "SOCKET":
+ IP = self.option.get("InputSocketIP", "0.0.0.0")
+ Port = self.option.get("InputSocketPort", rannum(12000, 12300))
+
+ self._temp_ip = IP
+ self._temp_port = Port
+
+ self._temp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self._temp_socket.bind((IP, Port))
+
+ else:
+ raise "No Audio Device Supported"
+
+ def _running(self):
+ framesize = self.option.get("InputFrameSize", 1024)
+ samplesrates = self.option.get("SamplesRates", 48000)
+
+ while self.running:
+ # get audio
+ if self.audioinput == "DEVICE":
+ pcm = np.frombuffer(self.sourceinput.read(framesize, exception_on_overflow=False), dtype=np.int16)
+ elif self.audioinput == "WAV":
+ pcm = np.frombuffer(self.sourceinput.readframes(framesize * 2), dtype=np.int16)
+ if len(pcm) == 0:
+ self.sourceinput.rewind()
+
+ if self.standalone:
+ time.sleep(framesize / samplesrates)
+
+ elif self.audioinput == "SOCKET":
+ pcm = np.frombuffer(self.sourceinput.recv(framesize), dtype=np.int16)
+ else:
+ raise "no input data support"
+
+
+
+ # encode audio
+ if self.audiocodec == "PCM":
+ self.buffer.put(pcm.tobytes())
+ elif self.audiocodec == "OPUS":
+ encoded_packets = self.encoder.buffered_encode(memoryview(bytearray(pcm)))
+ for encoded_packet, _, _ in encoded_packets:
+ self.buffer.put(encoded_packet.tobytes())
+
+
+ def startencoder(self):
+ self._createaudiosource()
+ self._createencoder()
+
+ if self.audioinput == "SOCKET":
+ self._temp_socket.listen(2)
+ print(f"[Socket Input Beta] {self.__class__.__name__} audio incoming server is running on {self._temp_ip}:{self._temp_port}. (PCM Data only)")
+ print(f"[Socket Input Beta] {self.__class__.__name__} waiting for data for start encoder")
+ self.sourceinput, addr = self._temp_socket.accept()
+ print(f"[Socket Input Beta] {self.__class__.__name__} {addr} is connected. encoder is starting")
+
+ self._temp_socket.settimeout(self.option.get("InputSocketTimeout", 0.1))
+
+ self.running = True
+ self.runningthread.start()
+
+
+ def stopencoder(self):
+ self.running = False
+ self.runningthread.join()
\ No newline at end of file