Created
November 10, 2024 18:13
-
-
Save ancientstraits/0c220d40f9868e294388f1b8ba26ed13 to your computer and use it in GitHub Desktop.
Revisions
-
ancientstraits created this gist
Nov 10, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,158 @@ import wave from pathlib import Path import json import time import sys import keyboard import pyaudio writing = False reverse = False reverse_key = {} paused = False pause_time = 0.0 poses = {} is_pressed = {} def n_samples_to_time(n_samples, sample_rate): total_secs = n_samples / sample_rate mins = total_secs // 60 secs = total_secs % 60 subsecs = (secs * 100) % 100 return f'{int(mins)}:{int(secs)}.{int(subsecs)} ' def pressed(key): if keyboard.is_pressed(key): if key in is_pressed and is_pressed[key]: return False else: # print(key) is_pressed[key] = True return True else: if key in is_pressed and is_pressed[key]: # print('no', key) is_pressed[key] = False return False def num_pressed(): for i in range(10): if pressed(str(i)): return str(i) return False def reverse_audio(audio, sample_size, chunk_size): ret = b'' for i in range(sample_size*chunk_size, 0, -sample_size): ret += audio[i-sample_size:i] return ret CHUNK = 1024 if len(sys.argv) < 3: print(f'Plays a wave file. Usage: {sys.argv[0]} infile.wav outfile.wav') sys.exit(-1) # load positions from save file save_file_path = sys.argv[1] + '.json' if Path(save_file_path).exists(): with open(save_file_path, 'r') as f: arr = json.loads(f.read()) for entry in arr: poses[entry['key']] = entry['offset'] reverse_key[entry['key']] = entry['reverse'] out = wave.open(sys.argv[2], 'wb') with wave.open(sys.argv[1], 'rb') as wf: out.setnchannels(wf.getnchannels()) out.setsampwidth(wf.getsampwidth()) out.setframerate(wf.getframerate()) # Instantiate PyAudio and initialize PortAudio system resources (1) p = pyaudio.PyAudio() # Open stream (2) stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), channels=wf.getnchannels(), rate=wf.getframerate(), output=True) # Play samples from the wave file (3) while True: print(f'\r{n_samples_to_time(wf.tell(), wf.getframerate())}', end='') if not paused: data = wf.readframes(CHUNK) if not len(data): break if reverse: data = reverse_audio(data, wf.getsampwidth()*wf.getnchannels(), CHUNK) stream.write(data) if writing: out.writeframes(data) if reverse: pos = wf.tell() - 2*CHUNK if pos < 0: reverse = False pos = 0 wf.setpos(pos) if pressed('esc'): break if pressed('space'): if paused and writing: out.writeframes(b'\x00' * wf.getsampwidth() * wf.getnchannels() * round( wf.getframerate() * (time.time() - pause_time) )) else: pause_time = time.time() paused = not paused if pressed('r'): reverse = not reverse if pressed('w'): writing = not writing if writing: print('Writing started') else: print('Writing stopped') seek_mul = 5 if keyboard.is_pressed('shift') else 1 if pressed('a'): pos = wf.tell() - seek_mul*wf.getframerate() if pos < 0: pos = 0 wf.setpos(pos) if pressed('d'): pos = wf.tell() + seek_mul*wf.getframerate() if (pos >= wf.getnframes()): pos = wf.getnframes() - 1 wf.setpos(pos) num = num_pressed() if not num: continue # print('OOOOOOOOOOOOO') if keyboard.is_pressed('ctrl'): pos = wf.tell() print(f'poses[{num}] = {pos}') poses[num] = pos reverse_key[num] = reverse elif (num in poses) and poses[num]: reverse = reverse_key[num] wf.setpos(poses[num]) # Close stream (4) stream.close() # Release PortAudio system resources (5) p.terminate() out.close() json_arr = [] for key in poses: json_arr.append({'key': key, 'offset': poses[key], 'reverse': reverse_key[key]}) with open(save_file_path, 'w') as f: f.write(json.dumps(json_arr))