Specify the audio stream to analyse

References #18.
This commit is contained in:
Alexander Kojevnikov 2016-04-24 18:49:59 -07:00
parent ac9c92df2d
commit 6cda85e118
4 changed files with 21 additions and 15 deletions

View File

@ -16,7 +16,7 @@ public:
AudioFileImpl( AudioFileImpl(
AudioError error, AVFormatContext *format_context, int audio_stream, AudioError error, AVFormatContext *format_context, int audio_stream,
const std::string& codec_name, int bit_rate, int sample_rate, int bits_per_sample, const std::string& codec_name, int bit_rate, int sample_rate, int bits_per_sample,
int channels, double duration int streams, int channels, double duration
); );
~AudioFileImpl() override; ~AudioFileImpl() override;
void start(int channel, int samples) override; void start(int channel, int samples) override;
@ -27,6 +27,7 @@ public:
int get_bit_rate() const override { return this->bit_rate; } int get_bit_rate() const override { return this->bit_rate; }
int get_sample_rate() const override { return this->sample_rate; } int get_sample_rate() const override { return this->sample_rate; }
int get_bits_per_sample() const override { return this->bits_per_sample; } int get_bits_per_sample() const override { return this->bits_per_sample; }
int get_streams() const override { return this->streams; }
int get_channels() const override { return this->channels; } int get_channels() const override { return this->channels; }
double get_duration() const override { return this->duration; } double get_duration() const override { return this->duration; }
const float *get_buffer() const override { return this->buffer; } const float *get_buffer() const override { return this->buffer; }
@ -42,6 +43,7 @@ private:
int bit_rate; int bit_rate;
int sample_rate; int sample_rate;
int bits_per_sample; int bits_per_sample;
int streams;
int channels; int channels;
double duration; double duration;
@ -70,7 +72,7 @@ Audio::~Audio()
av_lockmgr_register(nullptr); av_lockmgr_register(nullptr);
} }
std::unique_ptr<AudioFile> Audio::open(const std::string& file_name) std::unique_ptr<AudioFile> Audio::open(const std::string& file_name, int stream)
{ {
AudioError error = AudioError::OK; AudioError error = AudioError::OK;
@ -88,11 +90,14 @@ std::unique_ptr<AudioFile> Audio::open(const std::string& file_name)
} }
int audio_stream = -1; int audio_stream = -1;
int streams = 0;
if (!error) { if (!error) {
for (unsigned int i = 0; i < format_context->nb_streams; i++) { for (unsigned int i = 0; i < format_context->nb_streams; i++) {
if (format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { if (format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
audio_stream = i; if (stream == streams) {
break; audio_stream = i;
}
streams++;
} }
} }
if (audio_stream == -1) { if (audio_stream == -1) {
@ -100,12 +105,12 @@ std::unique_ptr<AudioFile> Audio::open(const std::string& file_name)
} }
} }
AVStream *stream = nullptr; AVStream *avstream = nullptr;
AVCodecContext *codec_context = nullptr; AVCodecContext *codec_context = nullptr;
AVCodec *codec = nullptr; AVCodec *codec = nullptr;
if (!error) { if (!error) {
stream = format_context->streams[audio_stream]; avstream = format_context->streams[audio_stream];
codec_context = stream->codec; codec_context = avstream->codec;
codec = avcodec_find_decoder(codec_context->codec_id); codec = avcodec_find_decoder(codec_context->codec_id);
if (!codec) { if (!codec) {
error = AudioError::NO_DECODER; error = AudioError::NO_DECODER;
@ -140,8 +145,8 @@ std::unique_ptr<AudioFile> Audio::open(const std::string& file_name)
} }
channels = codec_context->channels; channels = codec_context->channels;
if (stream->duration != AV_NOPTS_VALUE) { if (avstream->duration != AV_NOPTS_VALUE) {
duration = stream->duration * av_q2d(stream->time_base); duration = avstream->duration * av_q2d(avstream->time_base);
} else if (format_context->duration != AV_NOPTS_VALUE) { } else if (format_context->duration != AV_NOPTS_VALUE) {
duration = format_context->duration / (double) AV_TIME_BASE; duration = format_context->duration / (double) AV_TIME_BASE;
} else { } else {
@ -170,19 +175,19 @@ std::unique_ptr<AudioFile> Audio::open(const std::string& file_name)
return std::unique_ptr<AudioFile>(new AudioFileImpl( return std::unique_ptr<AudioFile>(new AudioFileImpl(
error, format_context, audio_stream, error, format_context, audio_stream,
codec_name, bit_rate, sample_rate, bits_per_sample, codec_name, bit_rate, sample_rate, bits_per_sample,
channels, duration streams, channels, duration
)); ));
} }
AudioFileImpl::AudioFileImpl( AudioFileImpl::AudioFileImpl(
AudioError error, AVFormatContext *format_context, int audio_stream, AudioError error, AVFormatContext *format_context, int audio_stream,
const std::string& codec_name, int bit_rate, int sample_rate, int bits_per_sample, const std::string& codec_name, int bit_rate, int sample_rate, int bits_per_sample,
int channels, double duration int streams, int channels, double duration
) : ) :
error(error), format_context(format_context), audio_stream(audio_stream), error(error), format_context(format_context), audio_stream(audio_stream),
codec_name(codec_name), bit_rate(bit_rate), codec_name(codec_name), bit_rate(bit_rate),
sample_rate(sample_rate), bits_per_sample(bits_per_sample), sample_rate(sample_rate), bits_per_sample(bits_per_sample),
channels(channels), duration(duration) streams(streams), channels(channels), duration(duration)
{ {
av_init_packet(&this->packet); av_init_packet(&this->packet);
this->packet.data = nullptr; this->packet.data = nullptr;

View File

@ -13,7 +13,7 @@ public:
Audio(); Audio();
~Audio(); ~Audio();
std::unique_ptr<AudioFile> open(const std::string& file_name); std::unique_ptr<AudioFile> open(const std::string& file_name, int stream);
}; };
class AudioFile class AudioFile
@ -29,6 +29,7 @@ public:
virtual int get_bit_rate() const = 0; virtual int get_bit_rate() const = 0;
virtual int get_sample_rate() const = 0; virtual int get_sample_rate() const = 0;
virtual int get_bits_per_sample() const = 0; virtual int get_bits_per_sample() const = 0;
virtual int get_streams() const = 0;
virtual int get_channels() const = 0; virtual int get_channels() const = 0;
virtual double get_duration() const = 0; virtual double get_duration() const = 0;
virtual const float *get_buffer() const = 0; virtual const float *get_buffer() const = 0;

View File

@ -374,7 +374,7 @@ void SpekSpectrogram::start()
if (samples > 0) { if (samples > 0) {
this->image.Create(samples, bits_to_bands(this->fft_bits)); this->image.Create(samples, bits_to_bands(this->fft_bits));
this->pipeline = spek_pipeline_open( this->pipeline = spek_pipeline_open(
this->audio->open(std::string(this->path.utf8_str())), this->audio->open(std::string(this->path.utf8_str()), 0),
this->fft->create(this->fft_bits), this->fft->create(this->fft_bits),
this->channel, this->channel,
this->window_function, this->window_function,

View File

@ -107,7 +107,7 @@ void test_audio()
for (const auto& item : files) { for (const auto& item : files) {
auto name = item.first; auto name = item.first;
auto info = item.second; auto info = item.second;
auto file = audio.open(SAMPLES_DIR "/" + name); auto file = audio.open(SAMPLES_DIR "/" + name, 0);
run( run(
"audio info: " + name, "audio info: " + name,
[&] () { test_info(file.get(), info); } [&] () { test_info(file.get(), info); }