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:
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) {