示例#1
0
    def load_roms(self):
        binary = self.load_rom(constants.project_to_absolute_path('res/c64kernal.bin'), 8192)
        if binary is not None:
            self.rom_kernal = binary
            self.has_kernal = True

        binary = self.load_rom(constants.project_to_absolute_path('res/c64basic.bin'), 8192)
        if binary is not None:
            self.rom_basic = binary
            self.has_basic = True

        binary = self.load_rom(constants.project_to_absolute_path('res/c64char.bin'), 4096)
        if binary is not None:
            self.rom_char = binary
            self.has_char = True
示例#2
0
def create_output_files(write_csv=True, write_midi=True):
    for entry in to_extract:
        (subtune, desc, seconds, starting_key, time_sig_top,
         time_sig_bottom) = entry

        sid = chiptunesak.SID()
        sid.set_options(
            sid_in_filename=sid_filename,
            subtune=subtune,
            tuning=448.93,  # above code figured this out
            vibrato_cents_margin=10,
            seconds=seconds,
            gcf_row_reduce=True,
        )

        filename_no_ext = 'examples/data/motl/motl_%s' % desc.replace(" ", "_")

        sid_dump = sid.capture()  # noqa: F841

        if write_csv:
            print("writing %s.csv" % filename_no_ext)
            sid.to_csv_file(
                project_to_absolute_path('%s.csv' % filename_no_ext))

        if write_midi:
            print("writing %s.mid" % filename_no_ext)
            rchirp_song = sid.to_rchirp(sid_filename)

            play_calls_per_quarter = 32  # can see this in the csv output
            # milliframes_per_quarter will determine the QPM/BPM
            chirp_song = \
                rchirp_song.to_chirp(milliframes_per_quarter=play_calls_per_quarter * 1000)

            chirp_song.set_key_signature(starting_key)
            chirp_song.set_time_signature(time_sig_top, time_sig_bottom)

            chiptunesak.MIDI().to_file(
                chirp_song,
                project_to_absolute_path('%s.mid' % filename_no_ext))
示例#3
0
def manage_resources(resources):
    headers = {
        'User-Agent':
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0'
    }

    for resource in resources:
        local_path = project_to_absolute_path(resource.local_path)

        # pathlib would have been better (can build full dir paths), but didn't work for me
        # pathlib.Path(local_path).parent.mkdir(parents=True, exist_ok=True)
        # TODO: this approach assumes parent dir exists.  Make a nested directory creator routine
        # and use it here.
        os.makedirs(local_path, exist_ok=True)

        local_file = os.path.normpath(
            os.path.join(local_path, resource.local_name))

        if os.path.exists(local_file):
            if not os.path.isfile(local_file):
                raise Exception('Error: not expecting "%s" to not be a file' %
                                (local_file))
            if SKIP_IF_EXISTS:
                print('"%s" exists, skipping' % (local_file))
                continue
            else:
                print('Will overwrite "%s"' % (local_file))

        print("%s -> %s" % (resource.remote_url, local_file))
        try:
            response = requests.get(resource.remote_url, headers=headers)
        except requests.exceptions.RequestException as e:
            print('Unable to download file at "%s", due to exception "%s"' %
                  (resource.remote_url, e))
            continue

        content = response.content

        if b'<html' in content.lower()[0:200]:
            print(
                'Warning: "%s" might merely be HTML saying the equivalent of "no botz allowed"'
                % (local_file))

        with open(local_file, 'wb') as out_file:
            out_file.write(content)

        time.sleep(uniform(1.5, 2.8))  # be friendly to web sites
        print()
示例#4
0
# Script to make sid header histograms for all the sids in an HVSC zip file

import operator
import zipfile
import itertools

from chiptunesak.constants import project_to_absolute_path
from chiptunesak import sid

# Assumes that the file is not double zipped
HVSC_LOG = project_to_absolute_path('res/HVSC72.zip')

histograms_categories = [
    'magic_id', 'version', 'data_offset', 'load_address', 'init_address',
    'play_address', 'num_subtunes', 'start_song', 'speed',
    'compute sid player', 'flag_1', 'clock', 'sid_model', 'sid2_model',
    'sid3_model', 'start_page', 'page_length', 'sid2_address', 'sid3_address',
    'sid_count', 'init_sets_irq', 'init_no_irq', 'contains_basic'
]
histograms = {category: {} for category in histograms_categories}


def update_hist(category, value):
    global histograms
    if value not in histograms[category]:
        histograms[category][value] = 0
    histograms[category][value] += 1


with zipfile.ZipFile(HVSC_LOG, 'r') as hvsc_zip:
    sid_files = [
示例#5
0
import chiptunesak
from chiptunesak.constants import project_to_absolute_path

"""
This minimal example imports a GoatTracker song and exports as MIDI.

"""

# Set up input and output paths
output_folder = str(project_to_absolute_path('examples\\data\\BWV_147')) + '\\'
input_folder = output_folder
input_file = str(project_to_absolute_path(input_folder + 'BWV_147_Bleibet.sng'))
output_midi_file = str(project_to_absolute_path(output_folder + 'BWV_147_Bleibet.mid'))

# Read in the song using the GoatTracker I/O class
print(f'Reading and converting {input_file}')
rchirp_song = chiptunesak.GoatTracker().to_rchirp(input_file, arch='PAL-C64')

# The song has a ritard at the end that will mess up the algorithm finding the beat, so eliminate it.
print(f'Removing the ritard at the end of the song')
rchirp_song.remove_tempo_changes()

# Turn the song into a ChirpSong object
print(f'Converting from RChirp to Chirp')
chirp_song = rchirp_song.to_chirp()

# We know the key signature and the time signature for the piece so set them (not required for playback)
print(f'Setting time and key signatures')
chirp_song.set_key_signature('G')
chirp_song.set_time_signature(3, 8)
示例#6
0
import copy

import chiptunesak
from chiptunesak.constants import project_to_absolute_path
"""
This example processes a MIDI file captured from Secret of Monkey Island to a GoatTracker song.

It shows the steps needed for this conversion:
  1. Scale and adjust the note data to correspond to musical notes and durations
  2. Split a track with chords into 3 separate tracks
  3. Assign GoatTracker instruments to the voices
  4. Export the 5-track to a stereo GoatTracker .sng file
"""

input_file = str(
    project_to_absolute_path(
        'examples/data/lechuck/MonkeyIsland_LechuckTheme.mid'))
output_midi_file = str(
    project_to_absolute_path('examples/data/lechuck/LeChuck.mid'))
output_gt_file = str(
    project_to_absolute_path('examples/data/lechuck/LeChuck.sng'))

chirp_song = chiptunesak.MIDI().to_chirp(input_file)

print(f'Original song:')
print(f'#tracks = {len(chirp_song.tracks)}')
print(f'    ppq = {chirp_song.metadata.ppq}')
print(f'  tempo = {chirp_song.metadata.qpm} qpm')
print('Track names:')
print('\n'.join(f'{i+1}:  {t.name}' for i, t in enumerate(chirp_song.tracks)))
print()
示例#7
0
# Make a SID for Jim Happel's last-minute CRX demo...

import chiptunesak
from chiptunesak.constants import project_to_absolute_path

input_mid_file = project_to_absolute_path(
    'examples\\data\\c128\\BWV_784_16th_to_8th.mid')
output_gt_file = project_to_absolute_path('examples\\temp\\BWV_784.sng')

chirp_song = chiptunesak.MIDI().to_chirp(input_mid_file,
                                         quantization='8',
                                         polyphony=False)

rchirp_song = chiptunesak.RChirpSong(chirp_song)
gt = chiptunesak.GoatTracker()

# TODO:  Dang, end_with_repeat=True seems to create an unplayable song.  Fix this
# after CRX
# gt.to_file(rchirp_song, output_gt_file, arch='NTSC-C64', end_with_repeat=True)
gt.to_file(rchirp_song, output_gt_file, arch='NTSC-C64')
示例#8
0
 1. Remove unused tracks, reorder and rename tracks to use
 2. Consolidate two tracks into one, changing instruments partway through
 3. Scale, move and adjust the note data to correspond to musical notes and durations
 4. Set minimum note lengths, quantize the song, and remove polyphony
 5. Truncate the captured song to a reasonable stopping point
 6. Convert the ChirpSong to an MChirpSong
 7. Use the Lilypond I/O object to write lilypond markup for the piece
 8. Convert the ChirpSong to an RChirpSong
 9. Assign GoatTracker instruments to the voices
10. Find repeated loops and compress the song
11. Export the GoatTracker .sng file

"""

output_folder = str(
    project_to_absolute_path('examples\\data\\mercantile')) + '\\'
input_folder = output_folder
input_file = str(
    project_to_absolute_path(input_folder + 'betrayalKrondorMercantile.mid'))
output_midi_file = str(
    project_to_absolute_path(output_folder + 'mercantile.mid'))
output_ly_file = str(project_to_absolute_path(output_folder + 'mercantile.ly'))
output_gt_file = str(project_to_absolute_path(output_folder +
                                              'mercantile.sng'))

# Read in the original MIDI to Chirp
chirp_song = chiptunesak.MIDI().to_chirp(input_file)

# First thing, we rename the song
chirp_song.metadata.name = "Betrayal at Krondor - Mercantile Theme"
chirp_song.metadata.composer = "Jan Paul Moorhead"
示例#9
0
import chiptunesak
from chiptunesak.constants import project_to_absolute_path
"""
This example shows how to convert a 3-voice song to C128 Basic:

 1. Import the song to chirp format from a MIDI file, quantizing the notes to the nearest 32nd note
 2. Since C128 BASIC cannot do notes shorter than a 16th note, perform a metric modulation to double note lengths
 3. Convert the song to mchirp format
 3. Save the BASIC as source
 4. Save the BASIC as a prg file

"""

output_folder = str(project_to_absolute_path('examples\\data\\C128')) + '\\'
input_folder = str(project_to_absolute_path('examples\\data\\common')) + '\\'
input_mid_file = input_folder + 'BWV_799.mid'
output_bas_file = output_folder + 'BWV_799.bas'
output_prg_file = output_folder + 'BWV_799.prg'

# Read in the MIDI song and quantize
chirp_song = chiptunesak.MIDI().to_chirp(input_mid_file,
                                         quantization='32',
                                         polyphony=False)

# When imported, the shortest note is a 32nd note, which is too fast for C128 BASIC.
# Perform a metric modulation by making every note length value twice as long, but
# increasing the tempo by the same factor so it sounds the same.  Now the shortest
# note will be a 16th note which the C128 BASIC can play.
print('Modulating music...')
chirp_song.modulate(2, 1)
示例#10
0
import os
import subprocess
import chiptunesak
from chiptunesak.constants import project_to_absolute_path
from chiptunesak.sid import SID
"""
This example shows how to do metric modulation to remove triplets
"""

file_name = 'Skyfox'
output_folder = str(project_to_absolute_path('examples/data/triplets/'))
input_folder = str(project_to_absolute_path('examples/data/sid/'))
input_sid_file = os.path.join(input_folder, file_name + '.sid')
output_mid_file = os.path.join(output_folder, file_name + '.mid')
output_mod_mid_file = os.path.join(output_folder, file_name + '_mod.mid')
output_ly_file = os.path.join(output_folder, file_name + '.ly')
output_ly_file_mod = os.path.join(output_folder, file_name + '_mod.ly')

sid = SID()

# Skyfox SID playback continues to repeat, 100 secs is enough
rchirp_song = sid.to_rchirp(input_sid_file, seconds=100)

# CSV shows 24 plays calls per quarter note
#    24 = 2^3 * 3; the factor of 3 is necessary for all the division-by-three rhythms
play_calls_per_quarter = 24
chirp_song = rchirp_song.to_chirp(
    milliframes_per_quarter=play_calls_per_quarter * 1000)

# the song is in the key of G and 4/4 time
chirp_song.set_key_signature('G')
示例#11
0
import chiptunesak
from chiptunesak.constants import project_to_absolute_path
"""
This example shows how to process a clip of a song into a PNG file using Lilypond using the following steps:

 1. Import the song to chirp format from a MIDI file, quantizing the notes to the nearest 16th note
 2. Convert the song to mchirp format
 3. Select the measures for the clip
 4. Save the lilypond source
 5. Run the lilypond converter from within python to generate the PNG file.

"""

output_folder = str(
    project_to_absolute_path('examples\\data\\lilypond')) + '\\'
input_folder = output_folder
input_file = input_folder + 'BWV_775.mid'
output_ly_file = output_folder + 'BWV_775.ly'

# Read in the MIDI song and quantize
chirp_song = chiptunesak.MIDI().to_chirp(input_file,
                                         quantization='16',
                                         polyphony=False)
# Convert to mchirp
mchirp_song = chirp_song.to_mchirp()

# Create the LilyPond I/O object
lp = chiptunesak.Lilypond()
# Set the format to do a clip and set the measures to the clip we want
lp.set_options(format='clip', measures=mchirp_song.tracks[0].measures[3:8])
示例#12
0
    def __str__(self):
        return "Ultima IV Music file {}, number of songs: {}".format(
            self.name, self.num_songs)

    def import_song_to_chirp(self, song_no):
        """
        Open and import a MIDI file into the ChirpSong representation.

        :param input_filename: Ultima IV filename.
        """
        song = Ultima4Song(song_no, self)
        return song.chirp_song


# Open the Ultima IV music file
musicPath = constants.project_to_absolute_path('examples/data/appleii_u4/')
f_songinfo = os.path.join(musicPath, 'u4songs.csv')
with open(f_songinfo, 'r') as csvfile:
    csvreader = csv.reader(csvfile, delimiter=",")
    rows = []
    for row in csvreader:
        rows.append(row)
    info = [dict(zip(rows[0], row)) for row in rows[1:]]

for song in info:
    print("Extracting song:", song['title'])
    music = Ultima4Music(os.path.join(musicPath, song['fname']))
    print("Number of songs in file: ", music.num_songs)
    chirp_song = music.import_song_to_chirp(int(song['songno']) - 1)
    midi_song = MIDI()
    output_filename = \
示例#13
0
# Export subtunes from Master of the Lamps for processing in Sibelius.
# Used to create this: https://www.youtube.com/watch?v=HH9sVayG0oQ
#
# Notes:
# - 3 genies * 7 pieces * (1 tunnel level + 1 music level) + final tunnel = 43 levels
#       odd numbers are tunnels, even numbers are genies
#       1st genie: level 1-14, 2nd genie: level 15-28, 3rd genie: level 29-42,
#       final tunnel: level 43
# - The starting key signatures (below) don't match the PAL subtunes this parses, instead
#       they should match the NTSC game footage (https://csdb.dk/release/?id=164839) that I
#       captured for the YouTube video that I'm going to match this music up with.

import chiptunesak
from chiptunesak.constants import project_to_absolute_path

sid_filename = project_to_absolute_path(
    'examples/data/sid/Master_of_the_Lamps_PAL.sid')

# list of subtunes to extract
to_extract = [
    # repeats every 1024 frames
    [10, "getting on carpet", 21, 'Ebm', 2, 4],
    [7, "carpet liftoff", 9, 'Em', 2, 4],
    [9, "fell off carpet", 9, 'Am', 4, 4],
    [8, "finished level", 12, 'C', 2, 4],
    [11, "game won", 23, 'C', 4, 4],

    # level 1, 15, 29
    [0, "tunnel 1", 77, 'C', 4, 4],

    # level 3, 17, 31
    [1, "tunnel 2", 86, 'Cm', 4, 4],
示例#14
0
import subprocess

import chiptunesak
from chiptunesak.constants import project_to_absolute_path
"""
This example shows how to process a song into PDF file using Lilypond using the following steps:

 1. Import the song to chirp format from a MIDI file, quantizing the notes to the nearest 32nd note
 2. Convert the song to mchirp format
 3. Save the lilypond source
 4. Run the lilypond converter from within python to generate the PDF file.

"""

output_folder = str(
    project_to_absolute_path('examples\\data\\lilypond')) + '\\'
input_folder = str(project_to_absolute_path('examples\\data\\common')) + '\\'
input_mid_file = input_folder + 'BWV_799.mid'
output_ly_file = output_folder + 'BWV_799.ly'

# Read in the MIDI song and quantize
chirp_song = chiptunesak.MIDI().to_chirp(input_mid_file,
                                         quantization='32',
                                         polyphony=False)

# It's in A minor, 3/8 time
chirp_song.set_key_signature('Am')
chirp_song.set_time_signature(3, 8)

# Convert to mchirp
mchirp_song = chirp_song.to_mchirp()