mirror of
https://github.com/alexkay/spek.git
synced 2025-04-20 10:27:38 +03:00
parent
925570cbb9
commit
7eef5eed6a
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user