From 1ef20ee017b11272e6b241a40e3413becaf4c0d6 Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Mon, 25 Mar 2013 13:40:59 +0000 Subject: much progress with audio format --- rotord/rotor.cpp | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 160 insertions(+), 16 deletions(-) (limited to 'rotord/rotor.cpp') diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index b8c5e2f..de9f4ea 100644 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -32,8 +32,10 @@ void Render_context::runTask() { //audio_analyser.process(audio_filename); //vampHost::runPlugin("","qm-vamp-plugins","qm-tempotracker", "",0, audio_filename, cerr,true); vector proc; + proc.push_back(new audio_thumbnailer()); if (load_audio(audio_filename,proc)) { state=AUDIO_READY; + //set the response } else state=IDLE; } @@ -290,6 +292,7 @@ bool Render_context::load_audio(const string &filename,vector avFormat(avformat_alloc_context(), &avformat_free_context); @@ -358,13 +361,12 @@ bool Render_context::load_audio(const string &filename,vectorsample_rate <<", channels: "<channels<<", sample format: "<sample_fmt<index) - continue; // the packet is not about the stream we want, let's jump again the start of the loop - } while(0); - */ + // suspect why was this in twice 210313 + //do { + // if (packet.packet.stream_index != stream->index) + /// continue; // the packet is not about the stream we want, let's jump again the start of the loop + //} while(0); + // // allocating an AVFrame std::shared_ptr avFrame(avcodec_alloc_frame(), &av_free); @@ -406,22 +408,22 @@ bool Render_context::load_audio(const string &filename,vectorsample_fmt) * CHAR_BIT; // 16 or 32 - unsigned int numberOfChannels = stream.codecContext->channels; // 1 for mono, 2 for stereo, or more - unsigned int numberOfSamplesContainedInTheFrame = stream.frame->nb_samples * stream.codecContext->channels; - unsigned int numberOfSamplesToPlayPerSecond = stream.codecContext->sample_rate; // usually 44100 or 48000 - const void* data = stream.frame->data[0]; - */ + + //unsigned int bitsPerSample = av_get_bytes_per_sample(stream.codecContext->sample_fmt) * CHAR_BIT; // 16 or 32 + //unsigned int numberOfChannels = stream.codecContext->channels; // 1 for mono, 2 for stereo, or more + //unsigned int numberOfSamplesContainedInTheFrame = stream.frame->nb_samples * stream.codecContext->channels; + //unsigned int numberOfSamplesToPlayPerSecond = stream.codecContext->sample_rate; // usually 44100 or 48000 + //const void* data = stream.frame->data[0]; + if (processedLength < 0) { //av_free_packet(&packet); shouldn't have to because of type safe wrapper - cerr <<"Error while processing the data"<< endl; + cerr <<"Error "<nb_streams; ++i) + { + if (formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) + { + audioStream = formatContext->streams[i]; + break; + } } + if (audioStream == NULL) + { + av_free(frame); + av_close_input_file(formatContext); + std::cout << "Could not find any audio stream in the file" << std::endl; + return false; + } + + AVCodecContext* codecContext = audioStream->codec; + + codecContext->codec = avcodec_find_decoder(codecContext->codec_id); + if (codecContext->codec == NULL) + { + av_free(frame); + av_close_input_file(formatContext); + std::cout << "Couldn't find a proper decoder" << std::endl; + return false; + } + else if (avcodec_open2(codecContext, codecContext->codec, NULL) != 0) + { + av_free(frame); + av_close_input_file(formatContext); + std::cout << "Couldn't open the context with the decoder" << std::endl; + return false; + } + + av_dump_format(formatContext, 0, 0, false); //avformat.h line 1256 + int samples = ((formatContext->duration + 5000)*codecContext->sample_rate)/AV_TIME_BASE; + + std::cout << "This stream has " << codecContext->channels << " channels, a sample rate of " << codecContext->sample_rate << "Hz and "<sample_fmt<< " (aka "<< av_get_sample_fmt_name(codecContext->sample_fmt) << ") "<init(codecContext->channels,16,samples); + } + + AVPacket packet; + av_init_packet(&packet); + + // Read the packets in a loop + while (av_read_frame(formatContext, &packet) == 0) + { + if (packet.stream_index == audioStream->index) + { + // Try to decode the packet into a frame + int frameFinished = 0; + int bytes = avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); + + // Some frames rely on multiple packets, so we have to make sure the frame is finished before + // we can use it + if (frameFinished) + { + // frame now has usable audio data in it. How it's stored in the frame depends on the format of + // the audio. If it's packed audio, all the data will be in frame->data[0]. If it's in planar format, + // the data will be in frame->data and possibly frame->extended_data. Look at frame->data, frame->nb_samples, + // frame->linesize, and other related fields on the FFmpeg docs. I don't know how you're actually using + // the audio data, so I won't add any junk here that might confuse you. Typically, if I want to find + // documentation on an FFmpeg structure or function, I just type " doxygen" into google (like + // "AVFrame doxygen" for AVFrame's docs) + + //std::cout << "Got a frame: bytes " << bytes << std::endl; + //now we can pass the data to the processor(s) + for (auto p: processors) { + p->process_frame(frame->data[0],frame->nb_samples); + } + + } + } + + // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory + av_free_packet(&packet); + } + + // Some codecs will cause frames to be buffered up in the decoding process. If the CODEC_CAP_DELAY flag + // is set, there can be buffered up frames that need to be flushed, so we'll do that + if (codecContext->codec->capabilities & CODEC_CAP_DELAY) + { + av_init_packet(&packet); + // Decode all the remaining frames in the buffer, until the end is reached + int frameFinished = 0; + int bytes = avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); + while (bytes >= 0 && frameFinished) + { + for (auto p: processors) { + p->process_frame(frame->data[0],frame->nb_samples); + } + } + } + + // Clean up! + av_free(frame); + avcodec_close(codecContext); + av_close_input_file(formatContext); + + + return true; } -- cgit v1.2.3