summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rotord/Makefile2
-rw-r--r--rotord/rotor.cpp176
-rwxr-xr-xrotord/rotor.h31
3 files changed, 187 insertions, 22 deletions
diff --git a/rotord/Makefile b/rotord/Makefile
index 3ccbfc2..d153562 100644
--- a/rotord/Makefile
+++ b/rotord/Makefile
@@ -1,5 +1,5 @@
# The pre-processor and compiler options.
-MY_CFLAGS = -fpermissive -std=c++11
+MY_CFLAGS = -fpermissive -std=c++11 -Wno-error
# -I ../ffmpeg
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<base_audio_processor*> 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<base_audio_process
//
//
+ /*
av_register_all();
std::shared_ptr<AVFormatContext> avFormat(avformat_alloc_context(), &avformat_free_context);
@@ -358,13 +361,12 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process
// decoding code here
//cerr << "audio codec context - sample rate: "<< audioCodec->sample_rate <<", channels: "<<audioCodec->channels<<", sample format: "<<audioCodec->sample_fmt<<endl;
- /* suspect why was this in twice 210313
- do {
- packet.reset(avFormat.get());
- 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);
- */
+ // 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> avFrame(avcodec_alloc_frame(), &av_free);
@@ -406,22 +408,22 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process
const auto processedLength = avcodec_decode_audio4(audioCodec.get(), avFrame.get(), &isFrameAvailable, &packetToSend);
//utils.c line 2018
-/*
- 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];
- */
+
+ //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 "<<processedLength<< " while processing the data"<< endl;
return false;
}
offsetInData += processedLength;
- /*
+
// processing the image if available
if (isFrameAvailable) {
// display image on the screen
@@ -432,8 +434,150 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process
}
*/
+
+ http://www.gamedev.net/topic/624876-how-to-read-an-audio-file-with-ffmpeg-in-c/
+ // Initialize FFmpeg
+ av_register_all();
+
+ AVFrame* frame = avcodec_alloc_frame();
+ if (!frame)
+ {
+ std::cout << "Error allocating the frame" << std::endl;
+ return false;
+ }
+
+ // you can change the file name "01 Push Me to the Floor.wav" to whatever the file is you're reading, like "myFile.ogg" or
+ // "someFile.webm" and this should still work
+ AVFormatContext* formatContext = NULL;
+ if (avformat_open_input(&formatContext, filename.c_str(), NULL, NULL) != 0)
+ {
+ av_free(frame);
+ std::cout << "Error opening the file" << std::endl;
+ return false;
+ }
+
+
+ if (avformat_find_stream_info(formatContext, NULL) < 0)
+ {
+ av_free(frame);
+ av_close_input_file(formatContext);
+ std::cout << "Error finding the stream info" << std::endl;
+ return false;
+ }
+
+ AVStream* audioStream = NULL;
+ // Find the audio stream (some container files can have multiple streams in them)
+ for (unsigned int i = 0; i < formatContext->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 "<<samples <<" samples" << std::endl;
+ std::cout << "The data is in format " <<codecContext->sample_fmt<< " (aka "<< av_get_sample_fmt_name(codecContext->sample_fmt) << ") "<<std::endl;
+
+ //we can now tell the processors the format
+ //we can work out the number of samples at this point
+
+
+
+
+ for (auto p: processors) {
+ p->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 "<name> 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;
}
diff --git a/rotord/rotor.h b/rotord/rotor.h
index c08371d..132059f 100755
--- a/rotord/rotor.h
+++ b/rotord/rotor.h
@@ -335,17 +335,38 @@ namespace Rotor {
};
class base_audio_processor {
public:
- base_audio_processor();
- base_audio_processor(int _channels,int _bits);
- virtual bool process_chunk(char *data,int num_samples);
- void init(int _channels,int _bits) {
+ virtual bool process_frame(uint8_t *data,int samples)=0;
+ void init(int _channels,int _bits,int _samples) {
channels=_channels;
bits=_bits;
+ samples=_samples;
};
- int channels,bits;
+ int channels,bits,samples;
};
class audio_thumbnailer: public base_audio_processor {
+ //how to deal with the fact that frames don't correspond with pixels?
+ //buffer the data somehow
+ //draw pixels based on rms value
public:
+ audio_thumbnailer(){
+ height=64;
+ width=512;
+ data=new uint8_t[height*width];
+ memset(data,0,height*width);
+ }
+ ~audio_thumbnailer(){
+ delete[] data;
+ }
+ void init(int _channels,int _bits,int _samples) {
+ base_audio_processor::init(_channels,_bits,_samples);
+ samples_per_column=samples/width();
+ }
+ bool process_frame(uint8_t *data,int samples){
+
+ return true;
+ }
+ uint8_t *data;
+ int height,width,samples_per_column;
};
class Render_context: public Poco::Task { //Poco task object
//manages a 'patchbay'