ref: 5d1618518207664aee4cd48ebad7967885db625e
parent: 6ff6d18ce7790aa8adc8889923f13eafc8414ab6
parent: 18a378eef755e01d6f5907dde97a4b272110b4f4
author: Paul Brossier <piem@piem.org>
date: Fri Mar 22 08:15:46 EDT 2013
Merge branch 'device' into develop
--- a/src/io/source.c
+++ b/src/io/source.c
@@ -21,6 +21,7 @@
#include "config.h"
#include "aubio_priv.h"
#include "fvec.h"
+#include "fmat.h"
#include "io/source.h"
#ifdef __APPLE__
#include "io/source_apple_audio.h"
@@ -59,6 +60,16 @@
#endif /* __APPLE__ */
}
+void aubio_source_do_multi(aubio_source_t * s, fmat_t * data, uint_t * read) {
+#ifdef __APPLE__
+ aubio_source_apple_audio_do_multi((aubio_source_apple_audio_t *)s->source, data, read);
+#else /* __APPLE__ */
+#if HAVE_SNDFILE
+ aubio_source_sndfile_do_multi((aubio_source_sndfile_t *)s->source, data, read);
+#endif /* HAVE_SNDFILE */
+#endif /* __APPLE__ */
+}
+
void del_aubio_source(aubio_source_t * s) {
if (!s) return;
#ifdef __APPLE__
@@ -81,3 +92,22 @@
#endif /* __APPLE__ */
}
+uint_t aubio_source_get_channels(aubio_source_t * s) {
+#ifdef __APPLE__
+ return aubio_source_apple_audio_get_channels((aubio_source_apple_audio_t *)s->source);
+#else /* __APPLE__ */
+#if HAVE_SNDFILE
+ return aubio_source_sndfile_get_channels((aubio_source_sndfile_t *)s->source);
+#endif /* HAVE_SNDFILE */
+#endif /* __APPLE__ */
+}
+
+uint_t aubio_source_seek (aubio_source_t * s, uint_t seek ) {
+#ifdef __APPLE__
+ return aubio_source_apple_audio_seek ((aubio_source_apple_audio_t *)s->source, seek);
+#else /* __APPLE__ */
+#if HAVE_SNDFILE
+ return aubio_source_sndfile_seek ((aubio_source_sndfile_t *)s->source, seek);
+#endif /* HAVE_SNDFILE */
+#endif /* __APPLE__ */
+}
--- a/src/io/source.h
+++ b/src/io/source.h
@@ -69,6 +69,20 @@
/**
+ read polyphonic vector of length hop_size from source object
+
+ \param s source object, created with ::new_aubio_source
+ \param read_to ::fmat_t of data to read to
+ \param read upon returns, equals to number of frames actually read
+
+ Upon returns, `read` contains the number of frames actually read from the
+ source. `hop_size` if enough frames could be read, less otherwise.
+
+*/
+void aubio_source_do_multi(aubio_source_t * s, fmat_t * read_to, uint_t * read);
+
+/**
+
get samplerate of source object
\param s source object, created with ::new_aubio_source
@@ -76,6 +90,28 @@
*/
uint_t aubio_source_get_samplerate(aubio_source_t * s);
+
+/**
+
+ get channels of source object
+
+ \param s source object, created with ::new_aubio_source
+ \return channels
+
+*/
+uint_t aubio_source_get_channels (aubio_source_t * s);
+
+/**
+
+ seek source object
+
+ \param s source object, created with ::new_aubio_source
+ \param pos position to seek to, in frames
+
+ \return 0 if sucessful, non-zero on failure
+
+*/
+uint_t aubio_source_seek (aubio_source_t * s, uint_t pos);
/**
--- a/src/io/source_apple_audio.c
+++ b/src/io/source_apple_audio.c
@@ -22,6 +22,7 @@
#include "config.h"
#include "aubio_priv.h"
#include "fvec.h"
+#include "fmat.h"
#include "io/source_apple_audio.h"
// ExtAudioFileRef, AudioStreamBasicDescription, AudioBufferList, ...
@@ -36,7 +37,8 @@
struct _aubio_source_apple_audio_t {
uint_t channels;
- uint_t samplerate;
+ uint_t samplerate; //< requested samplerate
+ uint_t source_samplerate; //< actual source samplerate
uint_t block_size;
char_t *path;
@@ -55,7 +57,6 @@
s->path = path;
s->block_size = block_size;
- s->channels = 1;
OSStatus err = noErr;
UInt32 propSize;
@@ -80,6 +81,8 @@
//AUBIO_DBG("sampling rate set to 0, automagically adjusting to %d\n", samplerate);
}
s->samplerate = samplerate;
+ s->source_samplerate = fileFormat.mSampleRate;
+ s->channels = fileFormat.mChannelsPerFrame;
AudioStreamBasicDescription clientFormat;
propSize = sizeof(clientFormat);
@@ -97,9 +100,9 @@
// set the client format description
err = ExtAudioFileSetProperty(s->audioFile, kExtAudioFileProperty_ClientDataFormat,
propSize, &clientFormat);
- if (err) { AUBIO_ERROR("error in ExtAudioFileSetProperty, %d\n", (int)err); goto beach;}
-
-#if 0
+ if (err) {
+ AUBIO_ERROR("error in ExtAudioFileSetProperty, %d\n", (int)err);
+#if 1
// print client and format descriptions
AUBIO_DBG("Opened %s\n", s->path);
AUBIO_DBG("file/client Format.mFormatID: : %3c%c%c%c / %c%c%c%c\n",
@@ -116,6 +119,8 @@
AUBIO_DBG("file/client Format.mBytesPerPacket : %6d / %d\n", (int)fileFormat.mBytesPerPacket , (int)clientFormat.mBytesPerPacket);
AUBIO_DBG("file/client Format.mReserved : %6d / %d\n", (int)fileFormat.mReserved , (int)clientFormat.mReserved);
#endif
+ goto beach;
+ }
// compute the size of the segments needed to read the input file
UInt32 samples = s->block_size * clientFormat.mChannelsPerFrame;
@@ -126,7 +131,7 @@
} else if (rateRatio > 1.) {
AUBIO_WRN("up-sampling %s from %0.2fHz to %0.2fHz\n", s->path, fileFormat.mSampleRate, clientFormat.mSampleRate);
} else {
- assert (segmentSize == samples );
+ assert ( segmentSize == samples );
//AUBIO_DBG("not resampling, segmentSize %d, block_size %d\n", segmentSize, s->block_size);
}
@@ -143,7 +148,7 @@
void aubio_source_apple_audio_do(aubio_source_apple_audio_t *s, fvec_t * read_to, uint_t * read) {
UInt32 c, v, loadedPackets = s->block_size;
OSStatus err = ExtAudioFileRead(s->audioFile, &loadedPackets, &s->bufferList);
- if (err) { AUBIO_ERROR("error in ExtAudioFileRead, %d\n", (int)err); goto beach;}
+ if (err) { AUBIO_ERROR("error in ExtAudioFileRead %s %d\n", s->path, (int)err); goto beach;}
short *data = (short*)s->bufferList.mBuffers[0].mData;
@@ -170,6 +175,35 @@
return;
}
+void aubio_source_apple_audio_do_multi(aubio_source_apple_audio_t *s, fmat_t * read_to, uint_t * read) {
+ UInt32 c, v, loadedPackets = s->block_size;
+ OSStatus err = ExtAudioFileRead(s->audioFile, &loadedPackets, &s->bufferList);
+ if (err) { AUBIO_ERROR("source_apple_audio: error in ExtAudioFileRead, %d\n", (int)err); goto beach;}
+
+ short *data = (short*)s->bufferList.mBuffers[0].mData;
+
+ smpl_t **buf = read_to->data;
+
+ for (v = 0; v < loadedPackets; v++) {
+ for (c = 0; c < s->channels; c++) {
+ buf[c][v] = SHORT_TO_FLOAT(data[ v * s->channels + c]);
+ }
+ }
+ // short read, fill with zeros
+ if (loadedPackets < s->block_size) {
+ for (v = loadedPackets; v < s->block_size; v++) {
+ for (c = 0; c < s->channels; c++) {
+ buf[c][v] = 0.;
+ }
+ }
+ }
+ *read = (uint_t)loadedPackets;
+ return;
+beach:
+ *read = 0;
+ return;
+}
+
void del_aubio_source_apple_audio(aubio_source_apple_audio_t * s){
OSStatus err = noErr;
if (!s || !s->audioFile) { return; }
@@ -181,8 +215,19 @@
return;
}
+uint_t aubio_source_apple_audio_seek (aubio_source_apple_audio_t * s, uint_t pos) {
+ SInt64 resampled_pos = (SInt64)ROUND( pos * s->source_samplerate * 1. / s->samplerate );
+ OSStatus err = ExtAudioFileSeek(s->audioFile, resampled_pos);
+ if (err) AUBIO_ERROR("source_apple_audio: error in ExtAudioFileSeek (%d)\n", (int)err);
+ return err;
+}
+
uint_t aubio_source_apple_audio_get_samplerate(aubio_source_apple_audio_t * s) {
return s->samplerate;
+}
+
+uint_t aubio_source_apple_audio_get_channels(aubio_source_apple_audio_t * s) {
+ return s->channels;
}
#endif /* __APPLE__ */
--- a/src/io/source_apple_audio.h
+++ b/src/io/source_apple_audio.h
@@ -75,6 +75,20 @@
/**
+ read polyphonic vector of length hop_size from source object
+
+ \param s source object, created with ::new_aubio_source_apple_audio
+ \param read_to ::fmat_t of data to read to
+ \param read upon returns, equals to number of frames actually read
+
+ Upon returns, `read` contains the number of frames actually read from the
+ source. `hop_size` if enough frames could be read, less otherwise.
+
+*/
+void aubio_source_apple_audio_do_multi(aubio_source_apple_audio_t * s, fmat_t * read_to, uint_t * read);
+
+/**
+
get samplerate of source object
\param s source object, created with ::new_aubio_source_apple_audio
@@ -82,6 +96,28 @@
*/
uint_t aubio_source_apple_audio_get_samplerate(aubio_source_apple_audio_t * s);
+
+/**
+
+ get channels of source object
+
+ \param s source object, created with ::new_aubio_source_apple_audio
+ \return number of channels
+
+*/
+uint_t aubio_source_apple_audio_get_channels(aubio_source_apple_audio_t * s);
+
+/**
+
+ seek source object
+
+ \param s source object, created with ::new_aubio_source
+ \param pos position to seek to, in frames
+
+ \return 0 if sucessful, non-zero on failure
+
+*/
+uint_t aubio_source_apple_audio_seek (aubio_source_apple_audio_t * s, uint_t pos);
/**
--- a/src/io/source_sndfile.c
+++ b/src/io/source_sndfile.c
@@ -26,8 +26,9 @@
#include <sndfile.h>
#include "aubio_priv.h"
-#include "source_sndfile.h"
#include "fvec.h"
+#include "fmat.h"
+#include "source_sndfile.h"
#include "temporal/resampler.h"
@@ -158,7 +159,7 @@
for (j = 0; j < read_samples / input_channels; j++) {
data[j] = 0;
for (i = 0; i < input_channels; i++) {
- data[j] += (smpl_t)s->scratch_data[input_channels*j+i];
+ data[j] += s->scratch_data[input_channels*j+i];
}
data[j] /= (smpl_t)input_channels;
}
@@ -170,10 +171,69 @@
#endif /* HAVE_SAMPLERATE */
*read = (int)FLOOR(s->ratio * read_samples / input_channels + .5);
+
+ if (*read < s->hop_size) {
+ for (j = *read; j < s->hop_size; j++) {
+ data[j] = 0;
+ }
+ }
+
}
+void aubio_source_sndfile_do_multi(aubio_source_sndfile_t * s, fmat_t * read_data, uint_t * read){
+ uint_t i,j, input_channels = s->input_channels;
+ /* do actual reading */
+ sf_count_t read_samples = sf_read_float (s->handle, s->scratch_data, s->scratch_size);
+
+ smpl_t **data;
+
+#ifdef HAVE_SAMPLERATE
+ if (s->ratio != 1) {
+ AUBIO_ERR("source_sndfile: no multi channel resampling yet");
+ return;
+ //data = s->input_data->data;
+ } else
+#endif /* HAVE_SAMPLERATE */
+ {
+ data = read_data->data;
+ }
+
+ /* de-interleaving data */
+ for (j = 0; j < read_samples / input_channels; j++) {
+ for (i = 0; i < input_channels; i++) {
+ data[i][j] = (smpl_t)s->scratch_data[input_channels*j+i];
+ }
+ }
+
+#ifdef HAVE_SAMPLERATE
+ if (s->resampler) {
+ //aubio_resampler_do(s->resampler, s->input_data, read_data);
+ }
+#endif /* HAVE_SAMPLERATE */
+
+ *read = (int)FLOOR(s->ratio * read_samples / input_channels + .5);
+
+ if (*read < s->hop_size) {
+ for (i = 0; i < input_channels; i++) {
+ for (j = *read; j < s->hop_size; j++) {
+ data[i][j] = 0.;
+ }
+ }
+ }
+
+}
+
uint_t aubio_source_sndfile_get_samplerate(aubio_source_sndfile_t * s) {
return s->samplerate;
+}
+
+uint_t aubio_source_sndfile_get_channels(aubio_source_sndfile_t * s) {
+ return s->input_channels;
+}
+
+uint_t aubio_source_sndfile_seek (aubio_source_sndfile_t * s, uint_t pos) {
+ uint_t resampled_pos = (uint_t)ROUND(pos * s->input_samplerate * 1. / s->samplerate);
+ return sf_seek (s->handle, resampled_pos, SEEK_SET);
}
void del_aubio_source_sndfile(aubio_source_sndfile_t * s){
--- a/src/io/source_sndfile.h
+++ b/src/io/source_sndfile.h
@@ -74,6 +74,20 @@
/**
+ read polyphonic vector of length hop_size from source object
+
+ \param s source object, created with ::new_aubio_source_sndfile
+ \param read_to ::fmat_t of data to read to
+ \param read upon returns, equals to number of frames actually read
+
+ Upon returns, `read` contains the number of frames actually read from the
+ source. `hop_size` if enough frames could be read, less otherwise.
+
+*/
+void aubio_source_sndfile_do_multi(aubio_source_sndfile_t * s, fmat_t * read_to, uint_t * read);
+
+/**
+
get samplerate of source object
\param s source object, created with ::new_aubio_source_sndfile
@@ -81,6 +95,28 @@
*/
uint_t aubio_source_sndfile_get_samplerate(aubio_source_sndfile_t * s);
+
+/**
+
+ get number of channels of source object
+
+ \param s source object, created with ::new_aubio_source_sndfile
+ \return number of channels
+
+*/
+uint_t aubio_source_sndfile_get_channels (aubio_source_sndfile_t * s);
+
+/**
+
+ seek source object
+
+ \param s source object, created with ::new_aubio_source_sndfile
+ \param pos position to seek to, in frames
+
+ \return 0 if sucessful, non-zero on failure
+
+*/
+uint_t aubio_source_sndfile_seek (aubio_source_sndfile_t *s, uint_t pos);
/**
--- a/tests/src/io/test-source.c
+++ b/tests/src/io/test-source.c
@@ -36,7 +36,7 @@
do {
aubio_source_do(s, vec, &read);
- // fvec_print (vec);
+ fvec_print (vec);
n_frames += read;
} while ( read == hop_size );
--- /dev/null
+++ b/tests/src/io/test-source_multi.c
@@ -1,0 +1,51 @@
+#include <aubio.h>
+#include "utils_tests.h"
+
+int main (int argc, char **argv)
+{
+ sint_t err = 0;
+ if (argc < 2) {
+ err = -2;
+ PRINT_ERR("not enough arguments\n");
+ PRINT_MSG("read a wave file as a mono vector\n");
+ PRINT_MSG("usage: %s <source_path> [samplerate] [hop_size]\n", argv[0]);
+ PRINT_MSG("examples:\n");
+ PRINT_MSG(" - read file.wav at original samplerate\n");
+ PRINT_MSG(" %s file.wav\n", argv[0]);
+ PRINT_MSG(" - read file.wav at 32000Hz\n");
+ PRINT_MSG(" %s file.aif 32000\n", argv[0]);
+ PRINT_MSG(" - read file.wav at original samplerate with 4096 blocks\n");
+ PRINT_MSG(" %s file.wav 0 4096 \n", argv[0]);
+ return err;
+ }
+
+ uint_t samplerate = 0;
+ uint_t hop_size = 256;
+ uint_t n_frames = 0, read = 0;
+ if ( argc == 3 ) samplerate = atoi(argv[2]);
+ if ( argc == 4 ) hop_size = atoi(argv[3]);
+
+ char_t *source_path = argv[1];
+
+ aubio_source_t* s = new_aubio_source(source_path, samplerate, hop_size);
+ if (!s) { err = -1; goto beach; }
+
+ if (samplerate == 0 ) samplerate = aubio_source_get_samplerate(s);
+
+ fmat_t *mat = new_fmat(hop_size, aubio_source_get_channels(s) );
+
+ do {
+ aubio_source_do_multi (s, mat, &read);
+ fmat_print (mat);
+ n_frames += read;
+ } while ( read == hop_size );
+
+ PRINT_MSG("read %d frames at %dHz (%d blocks) from %s\n", n_frames, samplerate,
+ n_frames / hop_size, source_path);
+
+ del_aubio_source (s);
+beach:
+ del_fmat (mat);
+
+ return err;
+}