/**
    Applies polyphase FIR filter 

    Coefficients create a 24 kHz low pass filter for a 192 kHz wave
*/
void AudioProcessing::TestSimpleConvolution( const juce::File & input )
{
    const int polyphase4Size = sizeof(filterPhase0) / sizeof(float);
    const int convolutionSize = 4 * polyphase4Size;
    juce::AudioSampleBuffer convolutionFilter( 1, convolutionSize );

    float * data = convolutionFilter.getWritePointer( 0 );
    for ( int i = 0 ; i < polyphase4Size ; ++ i )
    {
        *data++ = filterPhase0[ i ];
        *data++ = filterPhase1[ i ];
        *data++ = filterPhase2[ i ];
        *data++ = filterPhase3[ i ];
    }

    juce::AudioFormatManager audioFormatManager;
    audioFormatManager.registerBasicFormats();

    juce::AudioFormatReader * reader = audioFormatManager.createReaderFor( input );

    if ( reader != nullptr )
    {
        // read file
        juce::AudioSampleBuffer origin( (int)reader->numChannels, (int)reader->lengthInSamples );
        reader->read( &origin, 0, (int)reader->lengthInSamples, 0, true, true );

        // Convolve
        juce::AudioSampleBuffer output;
        convolution( origin, convolutionFilter, output );
        output.applyGain(0.25f); // filter values use sample with 3 zeros per valid sample (1 / 4)

        juce::String outputName = input.getFullPathName().substring(0, input.getFullPathName().length() - 4);
        juce::File outputFile( outputName + "_convolution.wav" );
        juce::FileOutputStream * outputStream = new juce::FileOutputStream( outputFile );

        juce::WavAudioFormat wavAudioFormat;

        juce::StringPairArray emptyArray;
        juce::AudioFormatWriter * writer = wavAudioFormat.createWriterFor( 
            outputStream, reader->sampleRate, reader->numChannels, 24, emptyArray, 0 );

        if ( writer != nullptr )
        {
            writer->writeFromAudioSampleBuffer( output, 0, output.getNumSamples() );

            delete writer;
        }

        delete reader;
    }
}
void AudioProcessing::TestOversampling( const juce::File & input )
{
    juce::AudioFormatManager audioFormatManager;
    audioFormatManager.registerBasicFormats();

    juce::AudioFormatReader * reader = audioFormatManager.createReaderFor( input );

    if ( reader != nullptr )
    {
        // read file
        juce::AudioSampleBuffer origin( (int)reader->numChannels, (int)reader->lengthInSamples );
        reader->read( &origin, 0, (int)reader->lengthInSamples, 0, true, true );

        // Use polyphase FIR filter with coefficients for upsampling 4 times at 48KHz
        juce::AudioSampleBuffer output;
        polyphase4( origin, output );


        juce::String outputName = input.getFullPathName().substring(0, input.getFullPathName().length() - 4);
        juce::File outputFile( outputName + "_polyphase4.wav" );
        juce::FileOutputStream * outputStream = new juce::FileOutputStream( outputFile );

        juce::WavAudioFormat wavAudioFormat;

        juce::StringPairArray emptyArray;
        juce::AudioFormatWriter * writer = wavAudioFormat.createWriterFor( 
            outputStream, reader->sampleRate, reader->numChannels, 24, emptyArray, 0 );

        if ( writer != nullptr )
        {
            writer->writeFromAudioSampleBuffer( output, 0, output.getNumSamples() );
            
            delete writer;
        }

        delete reader;
    }
}
void CodeFileList::addDirectory (const juce::File& file)
{
    if (file.isDirectory())
    {
        juce::Array<juce::File> results;
        file.findChildFiles (results, juce::File::findFiles, true, wildcards);

        for (int i = results.size(); --i >= 0;)
            files.addIfNotAlreadyThere (results.getReference (i).getFullPathName()); //N.B.: Don't use addFile() - it will be a redundant check to see if the file is valid
    }
    else
    {
        addFile (file.getFullPathName());
    }
}
void InterfaceComponent::buttonClicked (juce::Button* button)
{
    if (button == &btnBrowse)
    {
        juce::FileChooser chooser ("Select the folder which contains the code files you want to modularise");
        
        if (chooser.browseForDirectory())
        {
            const juce::File folder (chooser.getResult());

            txtSourceFileFolder.setText (folder.getFullPathName().trim(), juce::sendNotification);
            txtDestinationFolder.setText (folder.getParentDirectory().getFullPathName().trim(), juce::sendNotification);

            files = Modulariser (folder, true).getFiles();

            fileListBox.setSelectedRows (juce::SparseSet<int>());
            fileListBox.updateContent();
        }
    }
    else if (button == &btnRefresh)
    {
        refresh();
    }
    else if (button == &btnGenerate)
    {
        const juce::String srcFolder (txtSourceFileFolder.getText().trim());
        const juce::String destFolder (txtDestinationFolder.getText().trim());

        if (srcFolder.isNotEmpty()
            && destFolder.isNotEmpty()
            && juce::File::isAbsolutePath (srcFolder)
            && juce::File::isAbsolutePath (destFolder))
        {
            Modulariser modulariser (files);

            modulariser.saveTo (juce::File (destFolder),
                                srcFolder,
                                txtModuleFilename.getText().trim(),
                                txtHeaderGuard.getText().trim(),
                                txtNamespace.getText().trim());
        }
    }
}
void CodeFileList::addFile (const juce::File& file)
{
    addFile (file.getFullPathName().trim());
}