|
@@ -1,8 +1,11 @@
|
|
|
import argparse
|
|
|
import audioop
|
|
|
import logging
|
|
|
+import math
|
|
|
import sys
|
|
|
+import struct
|
|
|
import time
|
|
|
+import threading
|
|
|
from functools import partial
|
|
|
|
|
|
import pymumble_py3 as pymumble
|
|
@@ -11,6 +14,32 @@ from pymumble_py3.constants import PYMUMBLE_CLBK_TEXTMESSAGERECEIVED
|
|
|
is_streaming = False
|
|
|
silence_time = 0
|
|
|
|
|
|
+SHORT_NORMALIZE = (1.0/32768.0)
|
|
|
+
|
|
|
+## peak detection
|
|
|
+
|
|
|
+def get_rms( block ):
|
|
|
+ # RMS amplitude is defined as the square root of the
|
|
|
+ # mean over time of the square of the amplitude.
|
|
|
+ # so we need to convert this string of bytes into
|
|
|
+ # a string of 16-bit samples...
|
|
|
+
|
|
|
+ # we will get one short out for each
|
|
|
+ # two chars in the string.
|
|
|
+ count = len(block)/2
|
|
|
+ format = "%dh"%(count)
|
|
|
+ shorts = struct.unpack( format, block )
|
|
|
+
|
|
|
+ # iterate over the block.
|
|
|
+ sum_squares = 0.0
|
|
|
+ for sample in shorts:
|
|
|
+ # sample is a signed short in +/- 32768.
|
|
|
+ # normalize it to 1.0
|
|
|
+ n = sample * SHORT_NORMALIZE
|
|
|
+ sum_squares += n*n
|
|
|
+
|
|
|
+ return math.sqrt( sum_squares / count )
|
|
|
+
|
|
|
|
|
|
def message_received(mumble, message):
|
|
|
global is_streaming
|
|
@@ -42,6 +71,11 @@ def get_parser():
|
|
|
help="Ignore commands in chat and stream everything",
|
|
|
)
|
|
|
parser.add_argument(
|
|
|
+ "--transmit",
|
|
|
+ action="store_true",
|
|
|
+ help="Transmit from your stdin",
|
|
|
+ )
|
|
|
+ parser.add_argument(
|
|
|
"--auto-suspend-stream",
|
|
|
action="store_true",
|
|
|
help="Ignore commands in chat and stream everything",
|
|
@@ -63,6 +97,22 @@ def get_parser():
|
|
|
return parser
|
|
|
|
|
|
|
|
|
+def transmit(name, mumble, chunk_size):
|
|
|
+ buffer = 0
|
|
|
+ while True:
|
|
|
+ try:
|
|
|
+ data = sys.stdin.buffer.read(int(chunk_size))
|
|
|
+ if(get_rms(data) > 0.09):
|
|
|
+ mumble.sound_output.add_sound(data)
|
|
|
+ buffer = 10005B
|
|
|
+ else:
|
|
|
+ # keep the audio open for one second
|
|
|
+ if(buffer >= 0):
|
|
|
+ mumble.sound_output.add_sound(data)
|
|
|
+ buffer -= 10
|
|
|
+ except IOError as e:
|
|
|
+ print( " Error recording: %s"%e )
|
|
|
+
|
|
|
def main():
|
|
|
global is_streaming
|
|
|
global silence_time
|
|
@@ -89,7 +139,8 @@ def main():
|
|
|
mumble.start()
|
|
|
mumble.is_ready() # Wait for client is ready
|
|
|
mumble.channels.find_by_tree(channel.split('/')).move_in()
|
|
|
- mumble.users.myself.mute()
|
|
|
+ if not args.transmit:
|
|
|
+ mumble.users.myself.mute()
|
|
|
|
|
|
if is_streaming:
|
|
|
mumble.users.myself.recording()
|
|
@@ -103,6 +154,10 @@ def main():
|
|
|
silent = b"\x00" * int(STEREO_CHUNK_SIZE)
|
|
|
cursor_time = time.time() - BUFFER
|
|
|
|
|
|
+ if args.transmit:
|
|
|
+ transmit_thread = threading.Thread(target=sound_recorder, args=(1,mumble, MONO_CHUNK_SIZE))
|
|
|
+ transmit_thread.start()
|
|
|
+
|
|
|
while mumble.is_alive():
|
|
|
if cursor_time < time.time() - BUFFER:
|
|
|
base_sound = None
|