Beispiel #1
0
def get_base_audio(input_foldername, bgm_filename, chart_data, no_bgm):
    if no_bgm:
        # Find last timestamp
        last_timestamp = int(sorted(chart_data['timestamp'].keys(), key=lambda x: int(x))[-1])

        # TODO: Find a better way to calculate the ending of the audio
        # Convert last timestamp into a duration and add 2 seconds in
        # case the final notes ring out for long
        duration = ((last_timestamp) / 0x12c) + 2

        # Create silent audio file
        output_audio = pydub.AudioSegment.silent(duration=duration * 1000)
    else:
        filename = os.path.join(input_foldername, bgm_filename)
        filename = helper.getCaseInsensitivePath(filename)
        output_audio = audio.get_audio_file(filename)

    return output_audio
Beispiel #2
0
def decode_at3(input, sample_rate, channels):
    data = bytearray(open(input, "rb").read())

    wav_header = bytearray()
    wav_header += bytearray("RIFF", "ascii")
    wav_header += int.to_bytes(len(data) + 0x3c, length=4, byteorder="little")
    wav_header += bytearray("WAVE", "ascii")

    wav_header += bytearray("fmt ", "ascii")
    wav_header += int.to_bytes(0x20, length=4, byteorder="little")

    format_id = 0x270
    byte_rate = 0x4099
    block_align = 0x180
    bits_per_sample = 0

    wav_header += int.to_bytes(format_id, length=2, byteorder="little")
    wav_header += int.to_bytes(channels, length=2, byteorder="little")
    wav_header += int.to_bytes(sample_rate, length=4, byteorder="little")
    wav_header += int.to_bytes(byte_rate, length=4, byteorder="little")
    wav_header += int.to_bytes(block_align, length=2, byteorder="little")
    wav_header += int.to_bytes(bits_per_sample, length=2, byteorder="little")

    wav_header += int.to_bytes(0x0e, length=2, byteorder="little")
    wav_header += int.to_bytes(0x01, length=2, byteorder="little")
    wav_header += int.to_bytes(0x1000, length=2, byteorder="little")
    wav_header += int.to_bytes(0x00, length=2, byteorder="little")
    wav_header += int.to_bytes(0x00, length=4, byteorder="little")
    wav_header += int.to_bytes(0x01, length=4, byteorder="little")

    wav_header += bytearray("data", "ascii")
    wav_header += int.to_bytes(len(data), length=4, byteorder="little")
    wav_header += data

    tmp_filename = tmpfile.mkstemp(suffix=".at3")
    with open(tmp_filename, "wb") as outfile:
        outfile.write(wav_header)

    sound = audio.get_audio_file(tmp_filename)

    tmpfile.tmpcleanup()
    return sound
Beispiel #3
0
def create_wav_from_chart(chart_data,
                          input_foldername,
                          sound_metadata,
                          output_filename,
                          bgm_filename="bgm.wav",
                          tags=None,
                          no_bgm=False,
                          ext="mp3",
                          quality="320k",
                          volume_part=100,
                          volume_bgm=100,
                          volume_auto=100,
                          ignore_auto=False):

    output_audio = get_base_audio(input_foldername, bgm_filename, chart_data,
                                  no_bgm)
    output_audio = make_silent(output_audio)

    if volume_bgm != 100:
        volume_bgm_db = percentage_to_db(volume_bgm)
        if not volume_bgm_db:
            output_audio = make_silent(output_audio)
        elif volume_bgm_db != 0:
            output_audio += volume_bgm_db

    sound_files = {}

    for timestamp_key in sorted(chart_data['timestamp'].keys(),
                                key=lambda x: int(x)):
        for cd in chart_data['timestamp'][timestamp_key]:
            if cd['name'] != "note":
                continue

            if ignore_auto and (cd['data'].get('auto_volume', 0) != 0
                                or cd['data'].get('auto_note', 0) != 0):
                continue

            if 'volume' not in cd['data']:
                cd['data']['volume'] = 127

            is_auto = cd['data'].get(
                'auto_volume') == 1 and cd['data'].get('auto_note') != 0
            if is_auto:
                # Change 2/3 later if other games use different ratios
                cd['data']['volume'] = int(
                    round(cd['data']['volume'] * (2 / 3)))

            if 'pan' not in cd['data']:
                cd['data']['pan'] = 64

            volume = 127  # 100% volume
            pan = 64  # Center
            wav_filename = "%04x.wav" % int(cd['data']['sound_id'])

            sound_key = "%04d_%03d_%03d" % (cd['data']['sound_id'],
                                            cd['data']['volume'],
                                            cd['data']['pan'])

            if sound_metadata and 'entries' in sound_metadata:
                for sound_entry in sound_metadata['entries']:
                    if int(sound_entry['sound_id']) == int(
                            cd['data']['sound_id']):
                        volume = sound_entry.get('volume', volume)
                        pan = sound_entry.get('pan', pan)

                        if 'flags' not in sound_entry or "NoFilename" not in sound_entry[
                                'flags']:
                            wav_filename = sound_entry['filename']

                        break

            if sound_key not in sound_files:
                if cd['data'].get('volume'):
                    volume = (cd['data']['volume'] / 127) * (volume /
                                                             127) * 127

                if cd['data'].get('pan'):
                    pan = (cd['data']['pan'] - ((128 - pan) / 2)) / (128 / 2)
                else:
                    pan = (pan - (128 / 2)) / (128 / 2)

                wav_filename = find_sound_filename(
                    helper.getCaseInsensitivePath(
                        os.path.join(input_foldername, wav_filename)))
                if os.path.exists(wav_filename):
                    keysound = audio.get_audio_file(wav_filename)
                    keysound = keysound.pan(pan)
                    db = percentage_to_db((volume / 127) * 100)
                    keysound += db

                    if is_auto:
                        volume_key = volume_auto
                    else:
                        volume_key = volume_part

                    if volume_key != 100:
                        volume_db = percentage_to_db(volume_key)
                        if not volume_db:
                            keysound = make_silent(keysound)
                        elif volume_db != 0:
                            keysound += volume_db

                    sound_files[sound_key] = keysound
                else:
                    print("Couldn't find file: %s" % wav_filename)

            if sound_key in sound_files:
                position = int(timestamp_key) / 0x12c
                #print("Overlaying sound at %f" % position)
                output_audio = output_audio.overlay(sound_files[sound_key],
                                                    position=position * 1000)

    return output_audio
Beispiel #4
0
def generate_wav_from_json(params, generate_output_filename=True):
    input_json = params.get('input')
    input_foldername = params.get('sound_folder')
    output_filename = params.get('output')

    if not params.get('render_ext'):
        ext = os.path.splitext(output_filename)[-1]
        ext = ext.replace('.', '').strip()

        if not ext:
            ext = "mp3"

        params['render_ext'] = ext

    if not input_json:
        raise Exception("Couldn't find input data")

    json_data = json.loads(input_json)
    selected_difficulty = get_selected_difficulty(json_data, params)

    if not selected_difficulty:
        raise Exception("Couldn't find selected difficulty")

    bgms = []
    bgm_filename = None
    for chart_data in json_data['charts']:
        # Skip metadata charts and stuff not specified by the user
        if chart_data['header']['is_metadata'] != 0:
            continue

        if chart_data['header']['difficulty'] != selected_difficulty:
            continue

        game_type = ['drum', 'guitar',
                     'bass'][chart_data['header']['game_type']]
        if game_type not in params['parts']:
            continue

        if generate_output_filename:
            output_filename = get_output_filename(json_data, chart_data,
                                                  params)
        else:
            output_filename = params['output']

        tags = get_tags(json_data, chart_data)

        if not bgm_filename:
            bgm_filename = get_bgm_filename(json_data, chart_data,
                                            input_foldername)

        sound_metadata_type = ['drum', 'guitar',
                               'guitar'][chart_data['header']['game_type']]
        json_sound_metadata = get_sound_metadata(params, json_data,
                                                 input_foldername,
                                                 sound_metadata_type)
        if not json_sound_metadata:
            raise Exception("Couldn't find sound metadata")

        print("Exporting %s..." % output_filename)

        bgms.append(
            create_wav_from_chart(
                chart_data,
                input_foldername,
                json_sound_metadata,
                output_filename,
                bgm_filename,
                tags=tags,
                no_bgm=params.get('render_no_bgm', False),
                ext=params.get('render_ext', "mp3"),
                quality=params.get('render_quality', '320k'),
                volume_part=params.get('render_volume', 100),
                volume_bgm=params.get('render_volume_bgm', 100),
                volume_auto=params.get('render_volume_auto', 100),
                ignore_auto=params.get('render_ignore_auto', False)))

    if not bgm_filename:
        return

    print("Saving to %s..." % output_filename)

    if not params.get('render_no_bgm', False):
        output_audio = audio.get_audio_file(bgm_filename)
    else:
        if len(bgms) == 0:
            return

        output_audio = bgms[0]
        bgms = bgms[1:]

    for bgm in bgms:
        output_audio = output_audio.overlay(bgm)

    output_audio.export(params['output'],
                        format=params.get('render_ext', "mp3"),
                        tags={},
                        bitrate=params.get('render_quality', '320k'))
Beispiel #5
0
def fixup_dtx(filename, input_folder, output_folder, no_convert, resources):
    output_lines = []
    difficulty = None
    has_drum = False
    has_guitar = False
    has_bass = False

    print(filename)

    for line in open(filename, encoding='shift-jis'):
        line_orig = line.strip()
        line = line_orig.upper()

        # Get DTX filename from line
        if not line.startswith('#'):
            output_lines.append(line_orig)
            continue

        line = line[1:]
        while line[0] not in [':', ' ']:
            line = line[1:]

        cmd = line_orig[1:len(line_orig) - len(line)].strip().upper()

        line = line.strip()
        value = line_orig[-len(line):].strip()

        while value and value[0] in [':', ' ']:
            value = value[1:]

        head = line_orig[:-len(line)]

        if cmd == "COMMENT":
            difficulty = value
            continue

        elif cmd == "DLEVEL":
            has_drum = True
            output_lines.append(line_orig)

        elif cmd == "GLEVEL":
            has_guitar = True
            output_lines.append(line_orig)

        elif cmd == "BLEVEL":
            has_bass = True
            output_lines.append(line_orig)

        elif cmd in ["PREIMAGE", "PREVIEW"]:
            idx = 2
            ext = os.path.splitext(value)[1]

            convert_audio = False
            if ext == ".wav" and not no_convert:
                convert_audio = True
                # Convert to .ogg instead
                ext = ".ogg"

            target_filename = "pre%s" % (ext)

            while target_filename in reverse_filename_lookup and reverse_filename_lookup[
                    target_filename] != value:
                target_filename = "pre%d%s" % (idx, ext)
                idx += 1

            full_input_path = os.path.join(input_folder, value)

            if not os.path.exists(
                    full_input_path) and resources and os.path.exists(
                        resources):
                full_input_path = os.path.join(resources, value)

            full_target_path = os.path.join(output_folder, target_filename)
            if convert_audio:
                if not os.path.exists(full_target_path):
                    if os.path.exists(full_input_path):
                        print(full_input_path)
                        orig_audio = audio.get_audio_file(full_input_path)
                        orig_audio.export(full_target_path)
                        print(target_filename)

                    else:
                        print("Couldn't find", full_input_path)

            else:
                if os.path.exists(full_input_path):
                    shutil.copyfile(full_input_path, full_target_path)

                else:
                    print("Couldn't find", full_input_path)

            add_filename(value, target_filename)

            output_lines.append(head + target_filename)

        elif cmd.startswith("WAV") or cmd.startswith("AVI"):
            idx = 0
            ext = os.path.splitext(value)[1]

            convert_audio = False
            if ext == ".wav" and not no_convert:
                convert_audio = True
                # Convert to .ogg instead
                ext = ".ogg"

            target_filename = "%04d%s" % (idx, ext)

            while target_filename in reverse_filename_lookup and reverse_filename_lookup[
                    target_filename] != value:
                target_filename = "%04d%s" % (idx, ext)
                idx += 1

            full_input_path = os.path.join(input_folder, value)
            full_target_path = os.path.join(output_folder, target_filename)
            if convert_audio:
                if not os.path.exists(full_target_path):
                    if os.path.exists(full_input_path):
                        print(full_input_path)
                        orig_audio = audio.get_audio_file(full_input_path)
                        orig_audio.export(full_target_path)
                        print(target_filename)

                    else:
                        print("Couldn't find", full_input_path)

            else:
                if os.path.exists(full_input_path):
                    shutil.copyfile(full_input_path, full_target_path)

                else:
                    print("Couldn't find", full_input_path)

            add_filename(value, target_filename)

            output_lines.append(head + target_filename)

        else:
            output_lines.append(line_orig)

    prefix = None

    if difficulty:
        prefix = {
            "BASIC": "bsc",
            "ADVANCED": "adv",
            "EXTREME": "ext",
            "MASTER": "mst",
        }[difficulty.upper()]

    if not prefix:
        print("Couldn't figure out what to prefix this file", filename)
        exit(1)

    output_filename = "_".join(
        list(
            filter(None, [
                prefix, *[
                    "drum" if has_drum else None, "guitar"
                    if has_guitar else None, "bass" if has_bass else None
                ]
            ]))) + ".dtx"

    if not output_filename:
        print("Couldn't figure out what to name this file", filename)
        exit(1)

    open(os.path.join(output_folder, output_filename),
         "w",
         encoding='shift-jis').write("\n".join(output_lines))

    return output_filename