~mrp/aerodramus

c90878cc6afd0e8e2c5a8337745db62de3312b17 — Mark Penner 6 months ago ea167b3
use struct to hold sound file data
3 files changed, 67 insertions(+), 23 deletions(-)

M autotests/lib/aerodramus.test.cpp
M src/lib/aerodramus.cpp
M src/lib/aerodramus.h
M autotests/lib/aerodramus.test.cpp => autotests/lib/aerodramus.test.cpp +33 -12
@@ 7,19 7,20 @@
#include <sndfile.hh>
#include <vector>

class testCalc : public QObject
class TestLibAerodramus : public QObject
{
    Q_OBJECT

private:
private Q_SLOTS:
    void test_generate_signal();
    void test_SoundFile();
    void test_dB_from_point_source();
    void test_watts_needed_to_point_source();
    void test_zero_cross_histogram();
};

void testCalc::test_generate_signal()
void TestLibAerodramus::test_generate_signal()
{
    std::vector<int> expected = {61184633,    129059814,   204269818,   287478906,   379351158,  480519331,  591538390,   712818012,   844526607,
                                 986457416,   1137845183,  1297120045,  1461584630,  1627002232, 1787091105, 1932936664,  2052366558,  2129392880,


@@ 28,22 29,48 @@ void testCalc::test_generate_signal()
                                 -859537778,  1756478078,  1321907844,  -1835921813, -513399919, 2069999894, -1818534422, 904469646};
    QCOMPARE(Aerodramus::generate_signal(200, 20000, 0.001, 44100), expected);
}
void TestLibAerodramus::test_SoundFile()
{
    Aerodramus::SoundFile soundfile1{};
    QVERIFY2(!Aerodramus::write(soundfile1), "writing a file with an empty path should not succeed");
    QTemporaryFile tempfile;
    tempfile.open();
    std::string path = tempfile.fileName().toStdString();
    soundfile1.path = path;
    QVERIFY2(!Aerodramus::write(soundfile1), "writing a file with a valid path but empty format, channel, and samplerate should not succeed");
    std::vector<double> data{1, 0, -1};
    long int expected_size = data.size();
    soundfile1.sample_data = data;
    soundfile1.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
    soundfile1.channels = 1;
    soundfile1.samplerate = 44100;
    QVERIFY2(Aerodramus::write(soundfile1), "writing a file with a valid path and valid format, channel, and samplerate should succeed");
    Aerodramus::SoundFile soundfile2{Aerodramus::read(path)};
    QCOMPARE(soundfile2.sample_data.size(), expected_size);
    data = {0.1, 0.2, 1, 400.2, 0, -1111.22};
    expected_size = data.size();
    soundfile1.sample_data = data;
    soundfile1.format = SF_FORMAT_WAV | SF_FORMAT_PCM_32;
    QVERIFY2(Aerodramus::write(soundfile1), "writing a file with a valid path and valid format, channel, and samplerate should succeed");
    Aerodramus::SoundFile soundfile3 = Aerodramus::read(path);
    QCOMPARE(soundfile3.sample_data.size(), expected_size);
}

void testCalc::test_dB_from_point_source()
void TestLibAerodramus::test_dB_from_point_source()
{
    QCOMPARE(Aerodramus::dB_from_point_source(96, 1, 1), 96);
    QCOMPARE(Aerodramus::dB_from_point_source(90, 20, 120), 84.7712125471966);
    QCOMPARE(Aerodramus::dB_from_point_source(96, 1000, 0.5), 32.9897000433602);
}

void testCalc::test_watts_needed_to_point_source()
void TestLibAerodramus::test_watts_needed_to_point_source()
{
    QCOMPARE(Aerodramus::watts_needed_to_point_source(96, 1, 96), 1);
    QCOMPARE(Aerodramus::watts_needed_to_point_source(90, 20, 83), 79.8104925987552);
    QCOMPARE(Aerodramus::watts_needed_to_point_source(87, 400.9, 70.7), 3767.66354023559);
}

void testCalc::test_zero_cross_histogram()
void TestLibAerodramus::test_zero_cross_histogram()
{
    std::vector<int> expected = {2};
    QCOMPARE_EQ(Aerodramus::zero_cross_histogram({-1, -2, 0, 0, 1, 3, -2}, 1), expected);


@@ 51,12 78,6 @@ void testCalc::test_zero_cross_histogram()
    QCOMPARE_EQ(Aerodramus::zero_cross_histogram({-1, -2, 0, 0, 1, 3, -2}, 2), expected);
    expected = {2, 2};
    QCOMPARE_EQ(Aerodramus::zero_cross_histogram({-1, -2, 0, -1, 1, 3, -2}, 3), expected);
    QTemporaryFile file;
    file.open();
    Aerodramus::write_file(file.fileName().toStdString(), Aerodramus::generate_signal(200, 20000, 20, 44100), 44100);
    std::vector<float> raw_samples = Aerodramus::read_file(file.fileName().toStdString());
    expected = {449, 567, 712, 898, 1130, 1422, 1791, 2254, 2838, 3573, 4498, 5663, 7129, 8974, 11299, 14224, 17907, 22543, 28381, 35728};
    QCOMPARE_EQ(Aerodramus::zero_cross_histogram(raw_samples, 20), expected);
}
QTEST_MAIN(testCalc)
QTEST_MAIN(TestLibAerodramus)
#include "aerodramus.test.moc"

M src/lib/aerodramus.cpp => src/lib/aerodramus.cpp +22 -9
@@ 12,19 12,32 @@
#include <vector>

#include <sndfile.hh>
Aerodramus::SoundFile::SoundFile(long int size)
    : sample_data(size)
{
}

std::vector<float> Aerodramus::read_file(std::string file_name)
Aerodramus::SoundFile Aerodramus::read(std::string const &path)
{
    SndfileHandle file(file_name);
    std::vector<float> data(file.frames() * file.channels());
    file.read(&data.front(), file.frames());
    return data;
    SndfileHandle file_handle(path);
    long int size = file_handle.frames() * file_handle.channels();
    SoundFile soundfile(size);
    file_handle.read(soundfile.sample_data.data(), size);
    soundfile.samplerate = file_handle.samplerate();
    soundfile.channels = file_handle.channels();
    soundfile.format = file_handle.format();
    return soundfile;
}
bool Aerodramus::write_file(std::string file_name, std::vector<int> frames, int sample_rate)

bool Aerodramus::write(SoundFile const &soundfile)
{
    SndfileHandle file(file_name, SFM_WRITE, SF_FORMAT_FLAC | SF_FORMAT_PCM_16, 1, sample_rate);
    file.write(frames.data(), frames.size());
    return true;
    if (soundfile.path != "" && SndfileHandle::formatCheck(soundfile.format, soundfile.channels, soundfile.samplerate)) {
        SndfileHandle filehandle(soundfile.path, SFM_WRITE, soundfile.format, soundfile.channels, soundfile.samplerate);
        filehandle.write(soundfile.sample_data.data(), soundfile.sample_data.size());
        return true;
    } else {
        return false;
    }
}
std::vector<int> Aerodramus::generate_signal(int start_freq, int end_freq, float seconds, int sample_rate)
{

M src/lib/aerodramus.h => src/lib/aerodramus.h +12 -2
@@ 9,8 9,18 @@

namespace Aerodramus
{
std::vector<float> read_file(std::string file_name);
bool write_file(std::string file_name, std::vector<int> frames, int sample_rate);
struct SoundFile {
    SoundFile() = default;
    SoundFile(long int size);

    std::string path{""};
    std::vector<double> sample_data{};
    int samplerate{0};
    int channels{0};
    int format{0};
};
SoundFile read(std::string const &path);
bool write(SoundFile const &soundfile);

std::vector<int> generate_signal(int start_freq, int end_freq, float seconds, int sample_rate);
double dB_from_point_source(double sensitivity, double distance, double watts);