Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87925675 authored by Mathias Agopian's avatar Mathias Agopian Committed by Android (Google) Code Review
Browse files

Merge changes I5d62a6c2,Iebf76958,I8068f0f7

* changes:
  improve resample test
  change how we store the FIR coefficients
  improve SINC resampler performance
parents 48c6b262 3f71761c
Loading
Loading
Loading
Loading
+309 −72

File changed.

Preview size limit exceeded, changes collapsed.

+3 −2
Original line number Diff line number Diff line
@@ -50,12 +50,13 @@ private:

    template<int CHANNELS>
    inline void filterCoefficient(
            int32_t& l, int32_t& r, uint32_t phase, const int16_t *samples);
            int32_t& l, int32_t& r, uint32_t phase, const int16_t *samples, uint32_t vRL);

    template<int CHANNELS>
    inline void interpolate(
            int32_t& l, int32_t& r,
            const int32_t* coefs, int16_t lerp, const int16_t* samples);
            const int32_t* coefs, size_t offset,
            int32_t lerp, const int16_t* samples);

    template<int CHANNELS>
    inline void read(int16_t*& impulse, uint32_t& phaseFraction,
+260 −36

File changed.

Preview size limit exceeded, changes collapsed.

+102 −61
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <sys/stat.h>
#include <errno.h>
#include <time.h>
#include <math.h>

using namespace android;

@@ -61,31 +62,34 @@ struct HeaderWav {
};

static int usage(const char* name) {
    fprintf(stderr,"Usage: %s [-p] [-h] [-q <dq|lq|mq|hq|vhq>] [-i <input-sample-rate>] "
                   "[-o <output-sample-rate>] <input-file> <output-file>\n", name);
    fprintf(stderr,"-p              - enable profiling\n");
    fprintf(stderr,"-h              - create wav file\n");
    fprintf(stderr,"-q              - resampler quality\n");
    fprintf(stderr,"Usage: %s [-p] [-h] [-s] [-q {dq|lq|mq|hq|vhq}] [-i input-sample-rate] "
                   "[-o output-sample-rate] [<input-file>] <output-file>\n", name);
    fprintf(stderr,"    -p    enable profiling\n");
    fprintf(stderr,"    -h    create wav file\n");
    fprintf(stderr,"    -s    stereo\n");
    fprintf(stderr,"    -q    resampler quality\n");
    fprintf(stderr,"              dq  : default quality\n");
    fprintf(stderr,"              lq  : low quality\n");
    fprintf(stderr,"              mq  : medium quality\n");
    fprintf(stderr,"              hq  : high quality\n");
    fprintf(stderr,"              vhq : very high quality\n");
    fprintf(stderr,"-i              - input file sample rate\n");
    fprintf(stderr,"-o              - output file sample rate\n");
    fprintf(stderr,"    -i    input file sample rate\n");
    fprintf(stderr,"    -o    output file sample rate\n");
    return -1;
}

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

    const char* const progname = argv[0];
    bool profiling = false;
    bool writeHeader = false;
    int channels = 1;
    int input_freq = 0;
    int output_freq = 0;
    AudioResampler::src_quality quality = AudioResampler::DEFAULT_QUALITY;

    int ch;
    while ((ch = getopt(argc, argv, "phq:i:o:")) != -1) {
    while ((ch = getopt(argc, argv, "phsq:i:o:")) != -1) {
        switch (ch) {
        case 'p':
            profiling = true;
@@ -93,6 +97,9 @@ int main(int argc, char* argv[]) {
        case 'h':
            writeHeader = true;
            break;
        case 's':
            channels = 2;
            break;
        case 'q':
            if (!strcmp(optarg, "dq"))
                quality = AudioResampler::DEFAULT_QUALITY;
@@ -105,7 +112,7 @@ int main(int argc, char* argv[]) {
            else if (!strcmp(optarg, "vhq"))
                quality = AudioResampler::VERY_HIGH_QUALITY;
            else {
                usage(argv[0]);
                usage(progname);
                return -1;
            }
            break;
@@ -117,44 +124,64 @@ int main(int argc, char* argv[]) {
            break;
        case '?':
        default:
            usage(argv[0]);
            usage(progname);
            return -1;
        }
    }
    argc -= optind;
    argv += optind;

    if (argc != 2) {
        usage(argv[0]);
    const char* file_in = NULL;
    const char* file_out = NULL;
    if (argc == 1) {
        file_out = argv[0];
    } else if (argc == 2) {
        file_in = argv[0];
        file_out = argv[1];
    } else {
        usage(progname);
        return -1;
    }

    argv += optind;

    // ----------------------------------------------------------

    size_t input_size;
    void* input_vaddr;
    if (argc == 2) {
        struct stat st;
    if (stat(argv[0], &st) < 0) {
        if (stat(file_in, &st) < 0) {
            fprintf(stderr, "stat: %s\n", strerror(errno));
            return -1;
        }

    int input_fd = open(argv[0], O_RDONLY);
        int input_fd = open(file_in, O_RDONLY);
        if (input_fd < 0) {
            fprintf(stderr, "open: %s\n", strerror(errno));
            return -1;
        }

    size_t input_size = st.st_size;
    void* input_vaddr = mmap(0, input_size, PROT_READ, MAP_PRIVATE, input_fd,
            0);
        input_size = st.st_size;
        input_vaddr = mmap(0, input_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
        if (input_vaddr == MAP_FAILED ) {
            fprintf(stderr, "mmap: %s\n", strerror(errno));
            return -1;
        }

//    printf("input  sample rate: %d Hz\n", input_freq);
//    printf("output sample rate: %d Hz\n", output_freq);
//    printf("input mmap: %p, size=%u\n", input_vaddr, input_size);
    } else {
        double k = 1000; // Hz / s
        double time = (input_freq / 2) / k;
        size_t input_frames = size_t(input_freq * time);
        input_size = channels * sizeof(int16_t) * input_frames;
        input_vaddr = malloc(input_size);
        int16_t* in = (int16_t*)input_vaddr;
        for (size_t i=0 ; i<input_frames ; i++) {
            double t = double(i) / input_freq;
            double y = sin(M_PI * k * t * t);
            int16_t yi = floor(y * 32767.0 + 0.5);
            for (size_t j=0 ; j<channels ; j++) {
                in[i*channels + j] = yi;
            }
        }
    }

    // ----------------------------------------------------------

@@ -162,9 +189,9 @@ int main(int argc, char* argv[]) {
        int16_t* mAddr;
        size_t mNumFrames;
    public:
        Provider(const void* addr, size_t size) {
        Provider(const void* addr, size_t size, int channels) {
            mAddr = (int16_t*) addr;
            mNumFrames = size / sizeof(int16_t);
            mNumFrames = size / (channels*sizeof(int16_t));
        }
        virtual status_t getNextBuffer(Buffer* buffer,
                int64_t pts = kInvalidPTS) {
@@ -174,47 +201,61 @@ int main(int argc, char* argv[]) {
        }
        virtual void releaseBuffer(Buffer* buffer) {
        }
    } provider(input_vaddr, input_size);
    } provider(input_vaddr, input_size, channels);

    size_t output_size = 2 * 2 * ((int64_t) input_size * output_freq)
            / input_freq;
    size_t input_frames = input_size / (channels * sizeof(int16_t));
    size_t output_size = 2 * 4 * ((int64_t) input_frames * output_freq) / input_freq;
    output_size &= ~7; // always stereo, 32-bits

    void* output_vaddr = malloc(output_size);
    memset(output_vaddr, 0, output_size);

    AudioResampler* resampler = AudioResampler::create(16, 1, output_freq,
            quality);
    if (profiling) {
        AudioResampler* resampler = AudioResampler::create(16, channels,
                output_freq, quality);

        size_t out_frames = output_size/8;
        resampler->setSampleRate(input_freq);
        resampler->setVolume(0x1000, 0x1000);
    resampler->resample((int*) output_vaddr, out_frames, &provider);

    if (profiling) {
        memset(output_vaddr, 0, output_size);
        timespec start, end;
        clock_gettime(CLOCK_MONOTONIC_HR, &start);
        resampler->resample((int*) output_vaddr, out_frames, &provider);
        resampler->resample((int*) output_vaddr, out_frames, &provider);
        resampler->resample((int*) output_vaddr, out_frames, &provider);
        resampler->resample((int*) output_vaddr, out_frames, &provider);
        clock_gettime(CLOCK_MONOTONIC_HR, &end);
        int64_t start_ns = start.tv_sec * 1000000000LL + start.tv_nsec;
        int64_t end_ns = end.tv_sec * 1000000000LL + end.tv_nsec;
        int64_t time = end_ns - start_ns;
        int64_t time = (end_ns - start_ns)/4;
        printf("%f Mspl/s\n", out_frames/(time/1e9)/1e6);

        delete resampler;
    }

    AudioResampler* resampler = AudioResampler::create(16, channels,
            output_freq, quality);
    size_t out_frames = output_size/8;
    resampler->setSampleRate(input_freq);
    resampler->setVolume(0x1000, 0x1000);

    memset(output_vaddr, 0, output_size);
    resampler->resample((int*) output_vaddr, out_frames, &provider);

    // down-mix (we just truncate and keep the left channel)
    int32_t* out = (int32_t*) output_vaddr;
    int16_t* convert = (int16_t*) malloc(out_frames * sizeof(int16_t));
    int16_t* convert = (int16_t*) malloc(out_frames * channels * sizeof(int16_t));
    for (size_t i = 0; i < out_frames; i++) {
        int32_t s = out[i * 2] >> 12;
        for (int j=0 ; j<channels ; j++) {
            int32_t s = out[i * 2 + j] >> 12;
            if (s > 32767)       s =  32767;
            else if (s < -32768) s = -32768;
        convert[i] = int16_t(s);
            convert[i * channels + j] = int16_t(s);
        }
    }

    // write output to disk
    int output_fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC,
    int output_fd = open(file_out, O_WRONLY | O_CREAT | O_TRUNC,
            S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (output_fd < 0) {
        fprintf(stderr, "open: %s\n", strerror(errno));
@@ -222,11 +263,11 @@ int main(int argc, char* argv[]) {
    }

    if (writeHeader) {
        HeaderWav wav(out_frames*sizeof(int16_t), 1, output_freq, 16);
        HeaderWav wav(out_frames * channels * sizeof(int16_t), channels, output_freq, 16);
        write(output_fd, &wav, sizeof(wav));
    }

    write(output_fd, convert, out_frames * sizeof(int16_t));
    write(output_fd, convert, out_frames * channels * sizeof(int16_t));
    close(output_fd);

    return 0;
+19 −20
Original line number Diff line number Diff line
@@ -195,7 +195,8 @@ int main(int argc, char** argv)


    // total number of coefficients (one side)
    const int N = (1 << nz) * nzc;
    const int M = (1 << nz);
    const int N = M * nzc;

    // generate the right half of the filter
    if (!debug) {
@@ -220,13 +221,15 @@ int main(int argc, char** argv)
    }

    if (!polyphase) {
        for (int i=0 ; i<N ; i++) {
            double x = (2.0 * M_PI * i * Fcr) / (1 << nz);
            double y = kaiser(i+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;
        for (int i=0 ; i<=M ; i++) { // an extra set of coefs for interpolation
            for (int j=0 ; j<nzc ; j++) {
                int ix = j*M + i;
                double x = (2.0 * M_PI * ix * Fcr) / (1 << nz);
                double y = kaiser(ix+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;
                y *= atten;

                if (!debug) {
                if ((i % (1<<nz)) == 0)
                    if (j == 0)
                        printf("\n    ");
                }

@@ -238,6 +241,7 @@ int main(int argc, char** argv)
                    printf("%.9g%s ", y, debug ? "," : "f,");
                }
            }
        }
    } else {
        for (int j=0 ; j<polyN ; j++) {
            // calculate the phase
@@ -266,11 +270,6 @@ int main(int argc, char** argv)
    }

    if (!debug) {
        if (!format) {
            printf("\n    0x%08x ", 0);
        } else {
            printf("\n    %.9g ", 0.0f);
        }
        printf("\n};");
    }
    printf("\n");