#!/usr/bin/env python
# encoding: utf-8
"""
Chord Recognizer based on features extracted by a Convolutional Neural Network.

"""

from __future__ import absolute_import, division, print_function

import argparse

from madmom.features.chords import (CNNChordFeatureProcessor,
                                    CRFChordRecognitionProcessor,
                                    write_chords)
from madmom.features import ActivationsProcessor
from madmom.processors import io_arguments, IOProcessor


def main():
    p = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter, description='''
    The CNNChordRecognition program recognises major and minor chords in an
    audio file by first extracting learned features using a Convolutional
    Neural network, and then decoding the most likely chord sequence using a
    linear-chain Conditional Random Field, as described in

    Filip Korzeniowski and Gerhard Widmer,
    "A Fully Convolutional Deep Auditory Model for Musical Chord Recognition",
    Proceedings of IEEE International Workshop on Machine Learning for Signal
    Processing (MLSP), 2016.

    This method is computationally more expensive than the one implemented
    in DCChordRecognition but gives better results.

    This program can be run in 'single' file mode to process a single audio
    file and write the recognised chords to STDOUT or the given output file.

      $ CNNChordRecognition single INFILE [-o OUTFILE]

    The program can also be run in 'batch' mode to process multiple audio
    files and save the chords to files with the given suffix.

      $ CNNChordRecognition batch [-o OUTPUT_DIR] [-s OUTPUT_SUFFIX] FILES

    If no output directory is given, the program writes the files with the
    extracted chords to the same location as the audio files.

    The 'pickle' mode can be used to store the used parameters to be able to
    exactly reproduce experiments.

    '''
    )
    # version
    p.add_argument('--version', action='version',
                   version='CNNChordRecognition.2016')
    io_arguments(p, output_suffix='.chords.txt')
    ActivationsProcessor.add_arguments(p)

    args = p.parse_args()

    # set immutable arguments
    args.fps = 10

    if args.verbose:
        print(args)

    # input processor
    if args.load:
        # load activations (features) from a file
        in_processor = ActivationsProcessor(mode='r', **vars(args))
    else:
        in_processor = CNNChordFeatureProcessor(**vars(args))

    # output processor
    if args.save:
        # save activations (features) to a file
        out_processor = ActivationsProcessor(mode='w', **vars(args))
    else:
        # load conditional random field
        chord_processor = CRFChordRecognitionProcessor(**vars(args))
        out_processor = [chord_processor, write_chords]

    processor = IOProcessor(in_processor, out_processor)
    args.func(processor, **vars(args))


if __name__ == '__main__':
    main()
