Analyse a single channel

References #18.
This commit is contained in:
Alexander Kojevnikov 2016-04-05 11:27:06 -07:00
parent 925570cbb9
commit 7eef5eed6a
3 changed files with 54 additions and 56 deletions

View File

@ -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;

View File

@ -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;

View File

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