spek

Acoustic spectrum analyser
git clone http://git.hanabi.in/repos/spek.git
Log | Files | Refs | README

commit 7eef5eed6a2cae1300be6a70f34afe42981d63d4
parent 925570cbb92fcd575aa39e034c2c92ea2fead599
Author: Alexander Kojevnikov <alexander@kojevnikov.com>
Date:   Tue,  5 Apr 2016 11:27:06 -0700

Analyse a single channel

References #18.

Diffstat:
Msrc/spek-audio.cc | 93++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/spek-audio.h | 2+-
Msrc/spek-pipeline.cc | 15++++-----------
3 files changed, 54 insertions(+), 56 deletions(-)

diff --git a/src/spek-audio.cc b/src/spek-audio.cc @@ -1,3 +1,5 @@ +#include <assert.h> + extern "C" { #define __STDC_CONSTANT_MACROS #define __STDC_LIMIT_MACROS @@ -17,7 +19,7 @@ public: int channels, double duration ); ~AudioFileImpl() override; - void start(int samples) override; + void start(int channel, int samples) override; int read() override; AudioError get_error() const override { return this->error; } @@ -43,6 +45,8 @@ private: int channels; double duration; + int channel; + AVPacket packet; int offset; AVFrame *frame; @@ -217,8 +221,14 @@ AudioFileImpl::~AudioFileImpl() } } -void AudioFileImpl::start(int samples) +void AudioFileImpl::start(int channel, int samples) { + this->channel = channel; + if (channel < 0 || channel >= this->channels) { + assert(false); + this->error = AudioError::NO_CHANNELS; + } + AVStream *stream = this->format_context->streams[this->audio_stream]; int64_t rate = this->sample_rate * (int64_t)stream->time_base.num; int64_t duration = (int64_t)(this->duration * stream->time_base.den / stream->time_base.num); @@ -252,57 +262,52 @@ int AudioFileImpl::read() } // We have data, return it and come back for more later. int samples = this->frame->nb_samples; - int channels = this->channels; - int buffer_len = samples * channels; - if (buffer_len > this->buffer_len) { + if (samples > this->buffer_len) { this->buffer = static_cast<float*>( - av_realloc(this->buffer, buffer_len * sizeof(float)) + av_realloc(this->buffer, samples * sizeof(float)) ); - this->buffer_len = buffer_len; + this->buffer_len = samples; } AVSampleFormat format = static_cast<AVSampleFormat>(this->frame->format); int is_planar = av_sample_fmt_is_planar(format); - int i = 0; for (int sample = 0; sample < samples; ++sample) { - for (int channel = 0; channel < channels; ++channel) { - uint8_t *data; - int offset; - if (is_planar) { - data = this->frame->data[channel]; - offset = sample; - } else { - data = this->frame->data[0]; - offset = i; - } - float value; - switch (format) { - case AV_SAMPLE_FMT_S16: - case AV_SAMPLE_FMT_S16P: - value = reinterpret_cast<int16_t*>(data)[offset] - / static_cast<float>(INT16_MAX); - break; - case AV_SAMPLE_FMT_S32: - case AV_SAMPLE_FMT_S32P: - value = reinterpret_cast<int32_t*>(data)[offset] - / static_cast<float>(INT32_MAX); - break; - case AV_SAMPLE_FMT_FLT: - case AV_SAMPLE_FMT_FLTP: - value = reinterpret_cast<float*>(data)[offset]; - break; - case AV_SAMPLE_FMT_DBL: - case AV_SAMPLE_FMT_DBLP: - value = reinterpret_cast<double*>(data)[offset]; - break; - default: - value = 0.0f; - break; - } - this->buffer[i++] = value; + uint8_t *data; + int offset; + if (is_planar) { + data = this->frame->data[this->channel]; + offset = sample; + } else { + data = this->frame->data[0]; + offset = sample * this->channels; + } + float value; + switch (format) { + case AV_SAMPLE_FMT_S16: + case AV_SAMPLE_FMT_S16P: + value = reinterpret_cast<int16_t*>(data)[offset] + / static_cast<float>(INT16_MAX); + break; + case AV_SAMPLE_FMT_S32: + case AV_SAMPLE_FMT_S32P: + value = reinterpret_cast<int32_t*>(data)[offset] + / static_cast<float>(INT32_MAX); + break; + case AV_SAMPLE_FMT_FLT: + case AV_SAMPLE_FMT_FLTP: + value = reinterpret_cast<float*>(data)[offset]; + break; + case AV_SAMPLE_FMT_DBL: + case AV_SAMPLE_FMT_DBLP: + value = reinterpret_cast<double*>(data)[offset]; + break; + default: + value = 0.0f; + break; } + this->buffer[sample] = value; } - return buffer_len; + return samples; } if (this->packet.data) { this->packet.data -= this->offset; diff --git a/src/spek-audio.h b/src/spek-audio.h @@ -21,7 +21,7 @@ class AudioFile public: virtual ~AudioFile() {} - virtual void start(int samples) = 0; + virtual void start(int channel, int samples) = 0; virtual int read() = 0; virtual AudioError get_error() const = 0; diff --git a/src/spek-pipeline.cc b/src/spek-pipeline.cc @@ -95,7 +95,7 @@ struct spek_pipeline * spek_pipeline_open( p->input_size = p->nfft * (NFFT * 2 + 1); p->input = (float*)malloc(p->input_size * sizeof(float)); p->output = (float*)malloc(p->fft->get_output_size() * sizeof(float)); - p->file->start(samples); + p->file->start(0, samples); } return p; @@ -293,20 +293,13 @@ static void * reader_func(void *pp) } int pos = 0, prev_pos = 0; - int channels = p->file->get_channels(); int len; while ((len = p->file->read()) > 0) { if (p->quit) break; const float *buffer = p->file->get_buffer(); - while (len >= channels) { - float val = 0.0f; - for (int i = 0; i < channels; i++) { - val += buffer[i]; - } - p->input[pos] = val / channels; - buffer += channels; - len -= channels; + while (len-- > 0) { + p->input[pos] = *buffer++; pos = (pos + 1) % p->input_size; // Wake up the worker if we have enough data. @@ -314,7 +307,7 @@ static void * reader_func(void *pp) reader_sync(p, prev_pos = pos); } } - assert(len == 0); + assert(len == -1); } if (pos != prev_pos) {