Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3.9
- # -*- coding: utf-8 -*-
- # vim: set fileencoding=utf-8 :
- """
- Converts a 0cc-json-export into bytebeat code.
- No effects. Very basic volume and square control (hardcoded for each channel)
- Uses the engine found in BotB Entry 17669
- Author: @kleeder
- Created: 2022-07-22
- """
- import json
- import math
- with open("music.json", 'r') as f:
- occ_export = json.load(f)
- song_data = occ_export['songs'][0]
- class Module:
- rows = song_data['rows']
- speed = song_data['speed'] * 2
- tempo = song_data['tempo']
- frames = song_data['frames']
- channels = song_data['tracks'][0:4]
- class Bytebeat:
- frequencies = [
- 261.63,
- 277.18,
- 293.66,
- 311.13,
- 329.63,
- 349.23,
- 369.99,
- 392.00,
- 415.30,
- 440.00,
- 466.16,
- 493.88,
- ]
- noise_frequencies = [
- 440.0,
- 879.9,
- 1761.6,
- 2348.8,
- 3523.2,
- 4709.9,
- 7046.4,
- 8860.3,
- 11186.1,
- 13982.6,
- 18643.5,
- 27965.2,
- 55930.4,
- 111860.8,
- 223721.6,
- 447443.3,
- ]
- channel_pulses = [
- 50,
- 25,
- "''",
- "floor(t * (chan4_freq * 440 / SAMP_RATE) / 440)"
- ]
- channel_amps = [
- 25,
- 20,
- 50,
- 20
- ]
- channel_mix = [
- "chan1_amp * 2 * (floor(chan1_freq * t / SAMP_RATE * 256) % 256 <= chan1_pulse * 256 / 100) - chan1_amp",
- "chan2_amp * 2 * (floor(chan2_freq * t / SAMP_RATE * 256) % 256 <= chan2_pulse * 256 / 100) - chan2_amp",
- "chan3_amp / 128 * (17*abs(min(16-t*chan3_freq*32/SAMP_RATE%32|0,15))) - chan3_amp",
- "(chan4_amp / 128) * (floor(65536 * sin(chan4_pulse*chan4_pulse)) & 255) - chan4_amp"
- ]
- def frame_lookup(frame_number, patterns):
- for pattern in patterns:
- if pattern['index'] == frame_number:
- return pattern
- else:
- return {
- "notes": []
- }
- def get_note_frequency(note_value, is_tri, is_noise):
- if is_noise:
- return Bytebeat.noise_frequencies[note_value - 16]
- oct_dropdown = 3
- if is_tri:
- oct_dropdown = 4
- octave = math.floor(note_value / 12) - oct_dropdown
- which_note = note_value % 12
- byte_freq = Bytebeat.frequencies[which_note]
- if octave < 0:
- return byte_freq / (2 ** abs(octave))
- return byte_freq * (2 ** abs(octave))
- def convert_channel(channel, ch_index):
- global_tick = 0
- open_note = False
- chan_data = f"chan{ch_index + 1}_freq =\n"
- note_start = [
- "ERROR",
- "ERROR",
- False
- ]
- # C * (tick >= 0 && tick < 12)
- for frame in channel['frame_list']:
- pattern = frame_lookup(frame, channel['patterns'])
- chan_data += f"// pattern {frame}\n"
- for note in pattern['notes']:
- note_row = note['row']
- byte_tick = global_tick + note_row * Module.speed
- if note['note']['kind'] == 'note':
- note_value = note['note']['value']
- if open_note:
- chan_data += f"{note_start[0]} * (tick >= {note_start[1]} && tick < {byte_tick}) +"
- note_freq = get_note_frequency(note_value, (ch_index == 2), (ch_index == 3))
- note_start = [
- note_freq,
- byte_tick,
- ]
- open_note = True
- elif note['note']['kind'] == 'halt':
- if open_note:
- chan_data += f"{note_start[0]} * (tick >= {note_start[1]} && tick < {byte_tick}) +"
- open_note = False
- global_tick += Module.rows * Module.speed
- if open_note:
- chan_data += f"{note_start[0]} * (tick >= {note_start[1]} && tick < {global_tick}),\n"
- if chan_data.endswith("+") or chan_data.endswith("*"):
- chan_data = chan_data[:-1] + ","
- chan_data += f"\nchan{ch_index + 1}_amp = {Bytebeat.channel_amps[ch_index]},\nchan{ch_index + 1}_pulse = {Bytebeat.channel_pulses[ch_index]},\n"
- return chan_data
- bytebeat_file = f"""SAMP_RATE = 11025,\n
- BPM = {Module.tempo},\n
- beat = BPM * (t / SAMP_RATE) / 60,\n
- tick = floor(beat * 48) % {Module.frames * Module.rows * Module.speed},\n\n
- """
- byte_channel_data = []
- for i, channel in enumerate(Module.channels):
- byte_channel_data.append(convert_channel(channel, i))
- for byte_chan_data in byte_channel_data:
- bytebeat_file += byte_chan_data
- ch_mixing = "128 + " + "\n+ ".join(Bytebeat.channel_mix)
- bytebeat_file += ch_mixing
- with open("byte_convert.js", "w") as f:
- f.write(bytebeat_file)
- f.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement