Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds linux support using libsndfile #7

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions addon_config.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# All variables and this file are optional, if they are not present the PG and the
# makefiles will try to parse the correct values from the file system.
#
# Variables that specify exclusions can use % as a wildcard to specify that anything in
# that position will match. A partial path can also be specified to, for example, exclude
# a whole folder from the parsed paths from the file system
#
# Variables can be specified using = or +=
# = will clear the contents of that variable both specified from the file or the ones parsed
# from the file system
# += will add the values to the previous ones in the file or the ones parsed from the file
# system
#
# The PG can be used to detect errors in this file, just create a new project with this addon
# and the PG will write to the console the kind of error and in which line it is

meta:
ADDON_NAME = ofxAudioDecoder
ADDON_DESCRIPTION =
ADDON_AUTHOR =
ADDON_TAGS =
ADDON_URL =

common:
# dependencies with other addons, a list of them separated by spaces
# or use += in several lines
# ADDON_DEPENDENCIES = ofxSIMDFloats ofxMidi

# include search paths, this will be usually parsed from the file system
# but if the addon or addon libraries need special search paths they can be
# specified here separated by spaces or one per line using +=
# ADDON_INCLUDES =

# any special flag that should be passed to the compiler when using this
# addon
# ADDON_CFLAGS =

# any special flag that should be passed to the linker when using this
# addon, also used for system libraries with -lname
# ADDON_LDFLAGS =

# linux only, any library that should be included in the project using
# pkg-config
# ADDON_PKG_CONFIG_LIBRARIES =

# osx/iOS only, any framework that should be included in the project
# ADDON_FRAMEWORKS =

# source files, these will be usually parsed from the file system looking
# in the src folders in libs and the root of the addon. if your addon needs
# to include files in different places or a different set of files per platform
# they can be specified here
# ADDON_SOURCES =

# some addons need resources to be copied to the bin/data folder of the project
# specify here any files that need to be copied, you can use wildcards like * and ?
# ADDON_DATA =

# when parsing the file system looking for libraries exclude this for all or
# a specific platform
# ADDON_LIBS_EXCLUDE =

# when parsing the file system looking for sources exclude this for all or
# a specific platform
# ADDON_SOURCES_EXCLUDE =

# when parsing the file system looking for include paths exclude this for all or
# a specific platform
# ADDON_INCLUDES_EXCLUDE =

linux64:
# when parsing the file system looking for sources exclude this for all or
# a specific platform
ADDON_SOURCES_EXCLUDE = libs/include/%
ADDON_SOURCES_EXCLUDE += libs/src/%

linux:
# when parsing the file system looking for sources exclude this for all or
# a specific platform
ADDON_SOURCES_EXCLUDE = libs/include/%
ADDON_SOURCES_EXCLUDE += libs/src/%

msys2:
ADDON_SOURCES_EXCLUDE = libs/src/audiodecodercoreaudio.cpp
ADDON_SOURCES_EXCLUDE += libs/include/audiodecodercoreaudio.h
ADDON_SOURCES_EXCLUDE += libs/include/apple/%

vs:
# when parsing the file system looking for sources exclude this for all or
# a specific platform
ADDON_SOURCES_EXCLUDE = libs/src/audiodecodercoreaudio.cpp
ADDON_SOURCES_EXCLUDE += libs/include/audiodecodercoreaudio.h
ADDON_SOURCES_EXCLUDE += libs/include/apple/%

linuxarmv6l:
# when parsing the file system looking for sources exclude this for all or
# a specific platform
ADDON_SOURCES_EXCLUDE = libs/libaudiodecoder/%


linuxarmv7l:
# when parsing the file system looking for sources exclude this for all or
# a specific platform
ADDON_SOURCES_EXCLUDE = libs/include/%
ADDON_SOURCES_EXCLUDE += libs/src/%

android/armeabi:


android/armeabi-v7a:
# when parsing the file system looking for sources exclude this for all or
# a specific platform
ADDON_SOURCES_EXCLUDE = libs/include/%
ADDON_SOURCES_EXCLUDE += libs/src/%

osx:
ADDON_SOURCES_EXCLUDE = libs/src/audiodecodermediafoundation.cpp
ADDON_SOURCES_EXCLUDE += libs/include/audiodecodermediafoundation.h

ios:
ADDON_SOURCES_EXCLUDE = libs/src/audiodecodermediafoundation.cpp
ADDON_SOURCES_EXCLUDE += libs/include/audiodecodermediafoundation.h
Binary file added example/bin/data/demo.ogg
Binary file not shown.
Binary file added example/bin/example
Binary file not shown.
5 changes: 5 additions & 0 deletions example/src/ofApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
void ofApp::setup() {
ofSetVerticalSync(true);
ofSetFrameRate(120);
#ifndef __linux
loadFile("demo.mp3");
#else
loadFile("data/demo.ogg"); // directly specify path on linux
#endif

}

void ofApp::update() {
Expand Down
8 changes: 8 additions & 0 deletions libs/include/audiodecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ class DllExport AudioDecoder : public AudioDecoderMediaFoundation
{
public:
AudioDecoder(const std::string filename) : AudioDecoderMediaFoundation(filename) {};
private:
//Disable copy constructor and assignment operator
AudioDecoder(const AudioDecoder& that);
AudioDecoder& operator=(AudioDecoder const&);
};

#elif __APPLE__
Expand All @@ -57,6 +61,10 @@ class AudioDecoder : public AudioDecoderCoreAudio
{
public:
AudioDecoder(const std::string filename) : AudioDecoderCoreAudio(filename) {};
private:
//Disable copy constructor and assignment operator
AudioDecoder(const AudioDecoder& that);
AudioDecoder& operator=(AudioDecoder const&);
};
#endif

Expand Down
4 changes: 0 additions & 4 deletions libs/include/audiodecodercoreaudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,7 @@
#include "apple/CAStreamBasicDescription.h"

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#ifdef TARGET_OS_IPHONE
#include <MobileCoreServices/MobileCoreServices.h>
#elif defined TARGET_OS_MAC
#include <CoreServices/CoreServices.h>
#endif
#include <CoreAudio/CoreAudioTypes.h>
#include <AudioToolbox/AudioFile.h>
#include <AudioToolbox/AudioFormat.h>
Expand Down
13 changes: 4 additions & 9 deletions libs/src/audiodecodercoreaudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ AudioDecoderCoreAudio::~AudioDecoderCoreAudio() {
}

int AudioDecoderCoreAudio::open() {
std::cerr << "AudioDecoderCoreAudio::open()" << std::endl;


//Open the audio file.
OSStatus err;

Expand Down Expand Up @@ -106,13 +105,9 @@ int AudioDecoderCoreAudio::open() {
outputFormat.mFormatID = kAudioFormatLinearPCM;
outputFormat.mSampleRate = inputFormat.mSampleRate;
outputFormat.mChannelsPerFrame = 2;
#ifdef TARGET_OS_IPHONE
outputFormat.mFormatFlags = kAudioFormatFlagIsFloat;
#elif defined TARGET_OS_MAC
outputFormat.mFormatFlags = kAudioFormatFlagsCanonical;
//kAudioFormatFlagsCanonical means Native endian, float, packed on Mac OS X,
//but signed int for iOS instead.
#endif
outputFormat.mFormatFlags = kAudioFormatFlagsCanonical;
//kAudioFormatFlagsCanonical means Native endian, float, packed on Mac OS X,
//but signed int for iOS instead.

//Note iPhone/iOS only supports signed integers supposedly:
//outputFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger;
Expand Down
6 changes: 3 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ofxAudioDecoder is an [openFrameworks](http://openframeworks.cc/) wrapper for [libaudiodecoder](https://github.com/asantoni/libaudiodecoder/)
# ofxAudioDecoder is an [openFrameworks](http://openframeworks.cc/) wrapper for [libaudiodecoder](https://github.com/asantoni/libaudiodecoder/). On linux [libsndfile](http://www.mega-nerd.com/libsndfile/) is used instead

On OSX it can load .mp3, .m4a, .wav, and some other formats. Instead of being used for playback, it's meant for analysis. Because libaudiodecoder also supports Windows, with the addition of the Windows-specific sources and the creation of a Windows-specific project file ofxAudioDecoder should also run on windows.
On OSX it can load .mp3, .m4a, .wav, and some other formats. Instead of being used for playback, it's meant for analysis. Because libaudiodecoder also supports Windows, with the addition of the Windows-specific sources and the creation of a Windows-specific project file ofxAudioDecoder should also run on windows. On Linux it can load all the files supported by libsndfile, so no .mp3 support ( just use .wav or .ogg ).

## Example

The example project loads a file `demo.mp3` from the `data/` folder and draws the left and right channels into an `ofMesh`. You may drag and drop a file onto the OF app to load it and render the waveform.
The example project loads a file `demo.mp3` from the `data/` folder and draws the left and right channels into an `ofMesh`. You may drag and drop a file onto the OF app to load it and render the waveform.
57 changes: 56 additions & 1 deletion src/ofxAudioDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

//----------
bool ofxAudioDecoder::load(ofSoundBuffer & buffer, string filename, size_t framesToRead) {

#ifndef __linux
// ------------------------ loading using libaudiodecoder ------------------------
AudioDecoder audioDecoder(ofToDataPath(filename));
if (audioDecoder.open() != AUDIODECODER_OK) {
ofLogError() << "Failed to load " << filename;
Expand Down Expand Up @@ -33,10 +36,62 @@ bool ofxAudioDecoder::load(ofSoundBuffer & buffer, string filename, size_t frame
break;
}
}

#else
// ------------------------ linux loading using libsndfile ------------------------
const char * filePath_c = filename.c_str();

SndfileHandle fileHandle = SndfileHandle(filePath_c);

if( strcmp(fileHandle.strError(), "No Error.") !=0 ){
ofLogError() << "Failed to load " << filename;
return false;
}

auto numSamples = fileHandle.frames();
auto numChannels = fileHandle.channels();
auto sampleRate = fileHandle.samplerate();

buffer.setSampleRate(sampleRate);
buffer.allocate(numSamples / numChannels, numChannels);

//if user asked for 0 samples
if(framesToRead == 0) {
//we interpet that as wanting to read whole file
framesToRead = numSamples / numChannels;
}
int samplesToRead = framesToRead * numChannels;

// get the samples to a buffer
float* samples;
try
{
samples = new float [numChannels * numSamples];
}
catch (std::bad_alloc& ba)
{
std::string error = "error loading file: bad_alloc caught: ";
error += ba.what();
error +="\n";
ofLogError() << error <<"\n";
return false; //abort
}
fileHandle.read (samples, numChannels * numSamples);

int curSample = 0;
auto & rawSamples = buffer.getBuffer();
while(curSample < samplesToRead) {
rawSamples[curSample] = samples[curSample];
curSample++;
}

delete [] samples;

#endif

ofLogVerbose() << "Read " << curSample << " of " << numSamples;
return true;

}

//----------
Expand Down Expand Up @@ -72,4 +127,4 @@ const ofSoundBuffer & ofxAudioDecoder::getBuffer() const {
//----------
const vector<float> & ofxAudioDecoder::getRawSamples() const {
return this->buffer.getBuffer();
}
}
6 changes: 5 additions & 1 deletion src/ofxAudioDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

#include "ofMain.h"

#include <audiodecoder.h>
#ifdef __linux
#include <sndfile.hh>
#else
#include <audiodecoder.h>
#endif

class ofxAudioDecoder {
public:
Expand Down