diff --git a/mumble-bot/bot.py b/mumble-bot/bot.py index f5be254..b3d3931 100644 --- a/mumble-bot/bot.py +++ b/mumble-bot/bot.py @@ -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 @@ -41,6 +70,11 @@ def get_parser(): action="store_true", 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", @@ -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