Page 2 of 2

Re: LADSPA impulse response plugin.

Posted: Fri Feb 09, 2024 9:04 pm
by alex stone
alex stone wrote: Mon Feb 05, 2024 9:39 am
tramp wrote: Mon Feb 05, 2024 9:27 am

I've reworked the app a bit, so now it allow to convert stereo files as well. It will generate a header file per channel and apply _L / _R to the filename.
Also it's now possible to apply a gain correction value to adjust the levels. just give a float value to use after the filename.
Here is the advanced app:

Code: Select all

#include <stdio.h>
#include <iostream>
#include <filesystem>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>

using std::min;
// g++ -w -o sfconvert sfconvert.cpp -lsndfile

#include <sndfile.hh>

std::string space2underscore(std::string text) {
    std::replace(text.begin(), text.end(), ' ', '_');
    text.resize (text.size () - 4);
    return text;
}

std::string base_name(std::string const & path) {
    return space2underscore(path.substr(path.find_last_of("/\\") + 1));
}

int main(int argc, char *argv[]) {

if (argc < 2) {
    std::cerr << "Convert a wav file to a C float array\n"
       << "       please give a file path/name to convert\n"
       << "       To trim the output give the numbers of samples to be used\n"
       << "       Example: sfconvert my.wav 256\n" 
       << "       will create a file my.h with a float array of size 256\n" 
       << "       To apply a gain correction give a (float) value to use\n"
       << "       Example: sfconvert my.wav 0.86\n" 
       << "       will create a file my.h with gain reduced by 0.86\n" 
       << "       both options could be used independent\n" << std::endl;
    
    return 1;
}
std::string file = argv[1];
int clip = 0;
float gain = 1.0;
if (argc > 2) {
    for (int a = 2; a < argc; a++) {
        std::size_t pos{};
        std::string input(argv[a]);
        std::stoi(input, &pos);
        if (pos == input.size()) {
            clip = std::stoi(input);
        } else {
            std::stof(input, &pos);
            if (pos == input.size())
                gain = std::stof(input);
        }
    }
}

// struct to hols sound file info
SF_INFO info;
info.format = 0;

// Open the wave file for reading
SNDFILE *sndfile = sf_open(file.c_str(), SFM_READ, &info);

if (!sndfile) {
    std::cerr << "Error: could not open file" << std::endl;
    return 1;
}


std::vector<float> samples(info.frames * info.channels);
sf_readf_float(sndfile, &samples[0], info.frames * info.channels);
sf_close(sndfile);

int trim = (int)samples.size();
if (clip) trim = min(clip, (int)samples.size());

std::string ch = "";
if (info.channels > 1) ch = "_L";

for (int c = 0; c < info.channels; c++) {
    std::string name = base_name(file) + ch;
    std::string fname = name + ".h";
    FILE *fp;
    if((fp=freopen(fname.c_str(), "w" ,stdout))==NULL) {
        fprintf(stderr,"open failed\n");
        return 1;
    }

    printf( "float %s[] = {\n", name.c_str());
    printf( "   ");

    int j = 0;
    for (int i = 0; i < trim/info.channels; i++){
        if (i<info.frames-1)
            printf(" %f,", samples[i*info.channels+c] * gain);
        else
            printf(" %f", samples[i*info.channels+c] * gain);
        ++j;
        if (j>4) {
            printf( "\n   ");
            j = 0;
        }
    }
    printf( "  };");

    fclose(fp);
    ch = "_R";
}
return 0;
}

Thanks Tramp. I'll test this afternoon. The Gain value will be useful.

A quick follow up. I now have three IRs to choose from in the plugin, that i use often for orchestral pieces. Nothing's crashing, and the LSCP file i'm using in Linuxsampler seems happy with the additional ladspa passenger..

Thanks for the help, and the app. Another GUI bites the dust.... 8)