import argparse
import os
from typing import NoReturn

import librosa
import numpy as np
import soundfile

from bytesep.dataset_creation.pack_audios_to_hdf5s.instruments_solo import (
    read_csv as read_instruments_solo_csv,
)
from bytesep.dataset_creation.pack_audios_to_hdf5s.maestro import (
    read_csv as read_maestro_csv,
)
from bytesep.utils import load_random_segment


def create_evaluation(args) -> NoReturn:
    r"""Random mix and write out audios for evaluation.

    Args:
        violin_dataset_dir: str, the directory of the violin dataset
        piano_dataset_dir: str, the directory of the piano dataset
        evaluation_audios_dir: str, the directory to write out randomly selected and mixed audio segments
        sample_rate: int
        channels: int, e.g., 1 | 2
        evaluation_segments_num: int
        mono: bool

    Returns:
        NoReturn
    """

    # arguments & parameters
    violin_dataset_dir = args.violin_dataset_dir
    piano_dataset_dir = args.piano_dataset_dir
    evaluation_audios_dir = args.evaluation_audios_dir
    sample_rate = args.sample_rate
    channels = args.channels
    evaluation_segments_num = args.evaluation_segments_num
    mono = True if channels == 1 else False

    split = 'test'
    segment_seconds = 10.0

    random_state = np.random.RandomState(1234)

    violin_meta_csv = os.path.join(violin_dataset_dir, 'validation.csv')
    violin_names_dict = read_instruments_solo_csv(violin_meta_csv)
    violin_audio_names = violin_names_dict['{}'.format(split)]

    piano_meta_csv = os.path.join(piano_dataset_dir, 'maestro-v2.0.0.csv')
    piano_names_dict = read_maestro_csv(piano_meta_csv)
    piano_audio_names = piano_names_dict['{}'.format(split)]

    for source_type in ['violin', 'piano', 'mixture']:
        output_dir = os.path.join(evaluation_audios_dir, split, source_type)
        os.makedirs(output_dir, exist_ok=True)

    for n in range(evaluation_segments_num):

        print('{} / {}'.format(n, evaluation_segments_num))

        # Randomly select and write out a clean violin segment.
        violin_audio_name = random_state.choice(violin_audio_names)
        violin_audio_path = os.path.join(violin_dataset_dir, "mp3s", violin_audio_name)

        violin_audio = load_random_segment(
            audio_path=violin_audio_path,
            random_state=random_state,
            segment_seconds=segment_seconds,
            mono=mono,
            sample_rate=sample_rate,
        )
        # (channels_num, audio_samples)

        output_violin_path = os.path.join(
            evaluation_audios_dir, split, 'violin', '{:04d}.wav'.format(n)
        )
        soundfile.write(
            file=output_violin_path, data=violin_audio.T, samplerate=sample_rate
        )
        print("Write out to {}".format(output_violin_path))

        # Randomly select and write out a clean piano segment.
        piano_audio_name = random_state.choice(piano_audio_names)
        piano_audio_path = os.path.join(piano_dataset_dir, piano_audio_name)

        piano_audio = load_random_segment(
            audio_path=piano_audio_path,
            random_state=random_state,
            segment_seconds=segment_seconds,
            mono=mono,
            sample_rate=sample_rate,
        )
        # (channels_num, audio_samples)

        output_piano_path = os.path.join(
            evaluation_audios_dir, split, 'piano', '{:04d}.wav'.format(n)
        )
        soundfile.write(
            file=output_piano_path, data=piano_audio.T, samplerate=sample_rate
        )
        print("Write out to {}".format(output_piano_path))

        # Mix violin and piano segments and write out a mixture segment.
        mixture_audio = violin_audio + piano_audio
        # (channels_num, audio_samples)

        output_mixture_path = os.path.join(
            evaluation_audios_dir, split, 'mixture', '{:04d}.wav'.format(n)
        )
        soundfile.write(
            file=output_mixture_path, data=mixture_audio.T, samplerate=sample_rate
        )
        print("Write out to {}".format(output_mixture_path))


if __name__ == "__main__":
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "--violin_dataset_dir",
        type=str,
        required=True,
        help="The directory of the violin dataset.",
    )
    parser.add_argument(
        "--piano_dataset_dir",
        type=str,
        required=True,
        help="The directory of the piano dataset.",
    )
    parser.add_argument(
        "--evaluation_audios_dir",
        type=str,
        required=True,
        help="The directory to write out randomly selected and mixed audio segments.",
    )
    parser.add_argument(
        "--sample_rate",
        type=int,
        required=True,
        help="Sample rate",
    )
    parser.add_argument(
        "--channels",
        type=int,
        required=True,
        help="Audio channels, e.g, 1 or 2.",
    )
    parser.add_argument(
        "--evaluation_segments_num",
        type=int,
        required=True,
        help="The number of segments to create for evaluation.",
    )

    # Parse arguments.
    args = parser.parse_args()

    create_evaluation(args)

import argparse
import os
from typing import NoReturn

import librosa
import numpy as np
import soundfile

from bytesep.dataset_creation.pack_audios_to_hdf5s.instruments_solo import (
    read_csv as read_instruments_solo_csv,
)
from bytesep.dataset_creation.pack_audios_to_hdf5s.maestro import (
    read_csv as read_maestro_csv,
)
from bytesep.utils import load_random_segment


def create_evaluation(args) -> NoReturn:
    r"""Random mix and write out audios for evaluation.

    Args:
        violin_dataset_dir: str, the directory of the violin dataset
        piano_dataset_dir: str, the directory of the piano dataset
        evaluation_audios_dir: str, the directory to write out randomly selected and mixed audio segments
        sample_rate: int
        channels: int, e.g., 1 | 2
        evaluation_segments_num: int
        mono: bool

    Returns:
        NoReturn
    """

    # arguments & parameters
    violin_dataset_dir = args.violin_dataset_dir
    piano_dataset_dir = args.piano_dataset_dir
    evaluation_audios_dir = args.evaluation_audios_dir
    sample_rate = args.sample_rate
    channels = args.channels
    evaluation_segments_num = args.evaluation_segments_num
    mono = True if channels == 1 else False

    split = 'test'
    segment_seconds = 10.0

    random_state = np.random.RandomState(1234)

    violin_meta_csv = os.path.join(violin_dataset_dir, 'validation.csv')
    violin_names_dict = read_instruments_solo_csv(violin_meta_csv)
    violin_audio_names = violin_names_dict['{}'.format(split)]

    piano_meta_csv = os.path.join(piano_dataset_dir, 'maestro-v2.0.0.csv')
    piano_names_dict = read_maestro_csv(piano_meta_csv)
    piano_audio_names = piano_names_dict['{}'.format(split)]

    for source_type in ['violin', 'piano', 'mixture']:
        output_dir = os.path.join(evaluation_audios_dir, split, source_type)
        os.makedirs(output_dir, exist_ok=True)

    for n in range(evaluation_segments_num):

        print('{} / {}'.format(n, evaluation_segments_num))

        # Randomly select and write out a clean violin segment.
        violin_audio_name = random_state.choice(violin_audio_names)
        violin_audio_path = os.path.join(violin_dataset_dir, "mp3s", violin_audio_name)

        violin_audio = load_random_segment(
            audio_path=violin_audio_path,
            random_state=random_state,
            segment_seconds=segment_seconds,
            mono=mono,
            sample_rate=sample_rate,
        )
        # (channels_num, audio_samples)

        output_violin_path = os.path.join(
            evaluation_audios_dir, split, 'violin', '{:04d}.wav'.format(n)
        )
        soundfile.write(
            file=output_violin_path, data=violin_audio.T, samplerate=sample_rate
        )
        print("Write out to {}".format(output_violin_path))

        # Randomly select and write out a clean piano segment.
        piano_audio_name = random_state.choice(piano_audio_names)
        piano_audio_path = os.path.join(piano_dataset_dir, piano_audio_name)

        piano_audio = load_random_segment(
            audio_path=piano_audio_path,
            random_state=random_state,
            segment_seconds=segment_seconds,
            mono=mono,
            sample_rate=sample_rate,
        )
        # (channels_num, audio_samples)

        output_piano_path = os.path.join(
            evaluation_audios_dir, split, 'piano', '{:04d}.wav'.format(n)
        )
        soundfile.write(
            file=output_piano_path, data=piano_audio.T, samplerate=sample_rate
        )
        print("Write out to {}".format(output_piano_path))

        # Mix violin and piano segments and write out a mixture segment.
        mixture_audio = violin_audio + piano_audio
        # (channels_num, audio_samples)

        output_mixture_path = os.path.join(
            evaluation_audios_dir, split, 'mixture', '{:04d}.wav'.format(n)
        )
        soundfile.write(
            file=output_mixture_path, data=mixture_audio.T, samplerate=sample_rate
        )
        print("Write out to {}".format(output_mixture_path))


if __name__ == "__main__":
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "--violin_dataset_dir",
        type=str,
        required=True,
        help="The directory of the violin dataset.",
    )
    parser.add_argument(
        "--piano_dataset_dir",
        type=str,
        required=True,
        help="The directory of the piano dataset.",
    )
    parser.add_argument(
        "--evaluation_audios_dir",
        type=str,
        required=True,
        help="The directory to write out randomly selected and mixed audio segments.",
    )
    parser.add_argument(
        "--sample_rate",
        type=int,
        required=True,
        help="Sample rate",
    )
    parser.add_argument(
        "--channels",
        type=int,
        required=True,
        help="Audio channels, e.g, 1 or 2.",
    )
    parser.add_argument(
        "--evaluation_segments_num",
        type=int,
        required=True,
        help="The number of segments to create for evaluation.",
    )

    # Parse arguments.
    args = parser.parse_args()

    create_evaluation(args)

Random mix and write out audios for evaluation.      Args:         violin_dataset_dir: str, the directory of the violin dataset         piano_dataset_dir: str, the directory of the piano dataset         evaluation_audios_dir: str, the directory to write out randomly selected and mixed audio segments         sample_rate: int         channels: int, e.g., 1 | 2         evaluation_segments_num: int         mono: bool      Returns:         NoReturn # arguments & parameters # Randomly select and write out a clean violin segment. # (channels_num, audio_samples) # Randomly select and write out a clean piano segment. # (channels_num, audio_samples) # Mix violin and piano segments and write out a mixture segment. # (channels_num, audio_samples) # Parse arguments.