From abc34756d131b327eff548aa13aff8e4b677a96e Mon Sep 17 00:00:00 2001 From: Rangi42 Date: Thu, 23 Nov 2023 00:18:07 -0500 Subject: [PATCH] Remove pcm.py since pcm.c handles it --- tools/pokemontools/pcm.py | 156 -------------------------------------- 1 file changed, 156 deletions(-) delete mode 100644 tools/pokemontools/pcm.py diff --git a/tools/pokemontools/pcm.py b/tools/pokemontools/pcm.py deleted file mode 100644 index 428d57307..000000000 --- a/tools/pokemontools/pcm.py +++ /dev/null @@ -1,156 +0,0 @@ -# pcm.py -# Converts between .wav files and 1-bit pcm data. (pcm = pulse-code modulation) - -import argparse -import os -import struct -import wave - - -BASE_SAMPLE_RATE = 22050 - -def convert_to_wav(filenames=[]): - """ - Converts a file containing 1-bit pcm data into a .wav file. - """ - for filename in filenames: - with open(filename, 'rb') as pcm_file: - # Generate array of on/off pcm values. - samples = [] - byte = pcm_file.read(1) - while byte != "": - byte = struct.unpack('B', byte)[0] - for i in range(8): - bit_index = 7 - i - value = (byte >> bit_index) & 1 - samples.append(value) - byte = pcm_file.read(1) - - # Write a .wav file using the pcm data. - name, extension = os.path.splitext(filename) - wav_filename = name + '.wav' - wave_file = wave.open(wav_filename, 'w') - wave_file.setframerate(BASE_SAMPLE_RATE) - wave_file.setnchannels(1) - wave_file.setsampwidth(1) - - for value in samples: - if value > 0: - value = 0xff - - packed_value = struct.pack('B', value) - wave_file.writeframesraw(packed_value) - - wave_file.close() - - -def convert_to_pcm(filenames=[]): - """ - Converts a .wav file into 1-bit pcm data. - Samples in the .wav file are simply clamped to on/off. - - This currently works correctly on .wav files with the following attributes: - 1. Sample Width = 1 or 2 bytes (Some wave files use 3 bytes per sample...) - 2. Arbitrary sample sample_rate - 3. Mono or Stereo (1 or 2 channels) - """ - for filename in filenames: - samples, average_sample = get_wav_samples(filename) - - # Generate a list of clamped samples - clamped_samples = [] - for sample in samples: - # Clamp the raw sample to on/off - if sample < average_sample: - clamped_samples.append(0) - else: - clamped_samples.append(1) - - # The pcm data must be a multiple of 8, so pad the clamped samples with 0. - while len(clamped_samples) % 8 != 0: - clamped_samples.append(0) - - # Pack the 1-bit samples together. - packed_samples = bytearray() - for i in range(0, len(clamped_samples), 8): - # Read 8 pcm values to pack one byte. - packed_value = 0 - for j in range(8): - packed_value <<= 1 - packed_value += clamped_samples[i + j] - packed_samples.append(packed_value) - - # Open the output .pcm file, and write all 1-bit samples. - name, extension = os.path.splitext(filename) - pcm_filename = name + '.pcm' - with open(pcm_filename, 'wb') as out_file: - out_file.write(packed_samples) - - -def get_wav_samples(filename): - """ - Reads the given .wav file and returns a list of its samples after re-sampling - to BASE_SAMPLE_RATE. - Also returns the average sample amplitude. - """ - wav_file = wave.open(filename, 'r') - sample_width = wav_file.getsampwidth() - sample_count = wav_file.getnframes() - sample_rate = wav_file.getframerate() - num_channels = wav_file.getnchannels() - - samples = bytearray(wav_file.readframes(sample_count)) - - # Unpack the values based on the sample byte width. - unpacked_samples = [] - for i in range(0, len(samples), sample_width): - if sample_width == 1: - fmt = 'B' - elif sample_width == 2: - fmt = 'h' - else: - # todo: support 3-byte sample width - raise (Exception, "Unsupported sample width: " + str(sample_width)) - - value = struct.unpack(fmt, samples[i:i + sample_width])[0] - unpacked_samples.append(value) - - # Only keep the samples from the first audio channel. - unpacked_samples = unpacked_samples[::num_channels] - - # Approximate the BASE_SAMPLE_RATE. - # Also find the average amplitude of the samples. - resampled_samples = [] - total_value = 0 - interval = float(sample_rate) / BASE_SAMPLE_RATE - index = 0 - while index < sample_count: - sample = unpacked_samples[int(index)] - total_value += sample - - resampled_samples.append(sample) - index += interval - - average_sample = float(total_value) / len(resampled_samples) - - return resampled_samples, average_sample - - -def main(): - ap = argparse.ArgumentParser() - ap.add_argument('mode') - ap.add_argument('filenames', nargs='*') - args = ap.parse_args() - - method = { - 'wav': convert_to_wav, - 'pcm': convert_to_pcm, - }.get(args.mode, None) - - if method == None: - raise (Exception, "Unknown conversion method!") - - method(args.filenames) - -if __name__ == "__main__": - main()