9 #include <taglib/fileref.h>
10 #include <taglib/tag.h>
23 int mins = (
mLength - secs) / 60;
26 sprintf(dur,
"%d:0%d", mins, secs);
28 sprintf(dur,
"%d:%d", mins, secs);
29 logMsg(
"Tags: \"%s\" - %s - %s - %d - %s min",
31 logMsg(
" trk %d - %s - %d kbps - %d Hz - %d ch",
40 const char *
gSndFileExts[] = {
"mp3",
"wav",
"aiff",
"aif",
"mp4",
"m4p",
"m4b",
"m4a",
"aac",
"flac", 0 };
45 const char * dot = strrchr(path,
'.');
61 const char * lastDot = strrchr(path,
'.');
67 if (strcasestr(lastDot,
"wav"))
69 if (strcasestr(lastDot,
"mp3"))
70 return kSoundFileFormatMP3;
71 if (strcasestr(lastDot,
"aif"))
73 if (strcasestr(lastDot,
"aiff"))
75 if (strcasestr(lastDot,
"m4a"))
76 return kSoundFileFormatMP4;
77 if (strcasestr(lastDot,
"mp4"))
78 return kSoundFileFormatMP4;
79 if (strcasestr(lastDot,
"m4b"))
80 return kSoundFileFormatMP4;
81 if (strcasestr(lastDot,
"aac"))
82 return kSoundFileFormatAAC;
83 if (strcasestr(lastDot,
"flac"))
84 return kSoundFileFormatFLAC;
85 if (strcasestr(lastDot,
"caf"))
86 return kSoundFileFormatCAF;
87 if (strcasestr(lastDot,
"ogg"))
88 return kSoundFileFormatOGG;
89 if (strcasestr(lastDot,
"shn"))
90 return kSoundFileFormatSHN;
91 if (strcasestr(lastDot,
"snd"))
102 case kSoundFileFormatMP3:
return "audio/mpeg";
103 case kSoundFileFormatMP4:
return "audio/mp4a-latm";
105 default:
return "audio/basic";
114 mPath(string(tpath)),
115 mMode(kSoundFileClosed),
130 mProperties(otherSndFile.mProperties),
131 mMode(otherSndFile.mode()),
132 mIsValid(otherSndFile.isValid()),
133 mIsLooping(otherSndFile.isLooping()),
134 mStart(otherSndFile.startFrame()),
135 mStop(otherSndFile.stopFrame()),
136 mRate(otherSndFile.playbackRate()),
137 mBase(otherSndFile.mBase) {
199 mNumChannels = numChans;
210 logMsg(
"Abst_SoundFile::mergeToMono - buffers not allocated");
214 logMsg(
"Abst_SoundFile::mergeToMono - sound file already mono");
223 for (
unsigned j = 0; j < numCh; j++)
291 this->
addInput(CSL_RATE, frequency);
299 logMsg(
"FrequencyAmount::set scale input value");
344 TagLib::FileRef tfil(
mPath.c_str());
345 if ( ! tfil.isNull() && tfil.tag()) {
346 TagLib::Tag *tag = tfil.tag();
355 if( ! tfil.isNull() && tfil.audioProperties()) {
356 TagLib::AudioProperties *properties = tfil.audioProperties();
362 return !tfil.isNull();
371 const char * nam =
path().c_str();
372 if (strlen(nam) > 50)
373 logMsg(
"SndFile \"%s\"\n\t\t%d Hz, %d ch, %5.3f sec",
376 logMsg(
"SndFile \"%s\" - %d Hz, %d ch, %5.3f sec",
383 unsigned numFrames = outputBuffer.mNumFrames;
384 unsigned currentFrame = mCurrentFrame;
387 if (currentFrame >= (
unsigned) mStop) {
388 outputBuffer.zeroBuffers();
391 if (currentFrame + numFrames >= (
unsigned) mStop) {
392 numFrames = mStop - currentFrame;
393 outputBuffer.zeroBuffers();
395 if ( ! this->isCached(numFrames)) {
396 this->readBufferFromFile(numFrames);
402 if (scalePort->isFixed() && offsetPort->isFixed()
403 && (scaleValue == 1) && (offsetValue == 0)) {
404 unsigned numBytes = numFrames *
sizeof(
sample);
405 for (
unsigned i = 0; i < outputBuffer.mNumChannels; i++) {
406 int which =
csl_min(i, (mNumChannels - 1));
407 SampleBuffer sndPtr = mWavetable.buffer(which) + currentFrame;
409 memcpy(outPtr, sndPtr, numBytes);
413 for (
unsigned i = 0; i < outputBuffer.mNumChannels; i++) {
416 for (
unsigned j = 0; j < numFrames; j++) {
417 samp = (*dPtr++ * scaleValue) + offsetValue;
421 scalePort->resetPtr();
422 offsetPort->resetPtr();
427 this->setFrequency(mRate);
428 for (
unsigned i = 0; i < mNumChannels; i++)
431 currentFrame += numFrames;
432 if ((currentFrame >= (
unsigned) mStop) && mIsLooping)
434 mCurrentFrame = currentFrame;
469 unsigned start, stop;
471 if(fscanf(input,
"%s %u %u\n", cmName, &start, &stop) == 3) {
482 logMsg(
"\tSC: \"%s\" %d - %d (%.3f)\n",
492 unsigned numFrames = outputBuffer.mNumFrames;
493 unsigned toCopy = 0, toZero;
496 for (
unsigned h = 0; h < outputBuffer.mNumChannels; h++) {
497 out = outputBuffer.buffer(h);
498 if (mCurrent >= mStop) {
499 for (
unsigned i = 0; i < numFrames; i++)
503 SampleBuffer samps = (mFile->mWavetable.buffer(0)) + (mCurrent * mFile->channels()) + h;
504 if ( ! mFile->isValid()) {
505 fprintf(stderr,
"\tCannot play uncached sound file \"%s\"n", mName.c_str());
506 for (
unsigned i = 0; i < numFrames; i++)
512 if ((mCurrent + numFrames) >= (unsigned) mStop) {
513 toCopy = mStop - mCurrent;
514 toZero = numFrames - toCopy;
517 for (
unsigned i = 0; i < toCopy; i++)
519 for (
unsigned i = 0; i < toZero; i++)
543 #ifdef USE_SNDFILEBUFFER
552 #define SoundFile JSoundFile // JUCE snd file class
557 #define SoundFile LSoundFile // LibSndFile snd file class
562 #define SoundFile CASoundFile // CoreAudio snd file class
565 SoundFileBuffer::SoundFileBuffer(
string path,
unsigned numFrames)
574 mAreBuffersAllocated =
true;
575 mDidIAllocateBuffers =
false;
588 SoundFileBuffer::~SoundFileBuffer() { }
593 sample * SoundFileBuffer::samplePtrFor(
unsigned channel,
unsigned offset){
594 if ((mFile->base() <= offset) && (mFile->base() + mFile->cacheSize() > offset))
595 return(mFile->mWavetable.buffer(channel) + (offset - mFile->base()));
597 mFile->seekTo(offset);
598 mFile->readBufferFromFile(mFile->mWavetable.mNumFrames);
599 return(mFile->mWavetable.buffer(channel));
606 sample * SoundFileBuffer::samplePtrFor(
unsigned channel,
unsigned offset,
unsigned maxFrame){
607 if ((mFile->base() <= offset) && ((mFile->base() + mNumAlloc) > (offset + maxFrame)))
608 return (mFile->mWavetable.buffer(channel) + (offset - mFile->base()));
610 mFile->seekTo(offset);
611 mFile->readBufferFromFile(mFile->mWavetable.mNumFrames);
612 return(mFile->mWavetable.buffer(channel));
635 SampleFile::SampleFile() {
639 SampleFile::SampleFile(
string tpath,
unsigned MIDIKey,
double frequency,
double minRatio,
double maxRatio) {
643 SampleFile::~SampleFile() {
sample * SampleBuffer
1-channel buffer data type, vector of (sample)
#define UPDATE_SCALABLE_CONTROLS
void logMsg(const char *format,...)
These are the public logging messages.
UnitGenerator * mReadRate
my playback rate
#define kSoundFileFormatAIFF
unsigned mNumFrames
num frames used in each buffer
const char * gSndFileExts[]
Sound file name extensions we recognize - ToDo: should this be in a config file?
unsigned mNumFrames
sample frames
virtual void setBuffer(unsigned bufNum, SampleBuffer sPtr)
double mRate
sample rate ratio
csl::Status convertRate(int fromRate, int toRate)
convert the sample rate using libSampleRate
bool mAreBuffersAllocated
are the buffers allocated?
bool isActive()
answer if currently active
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
static unsigned sndFileFrames()
the default num frames that are cached
static const char * mimeType(const char *path)
Answer the MIME type based on the file name.
WavetableOscillator – Oscillator with a stored wave table that does table look-up. The default wave table is an 8192-sample sine. (perhaps accept a vector of freqs and a multichannel buffer?)
static SoundFileFormat sndfileNameType(const char *path)
Answer the snd file type.
unsigned mFrameRate
trigger ignored here
unsigned mBase
starting frame in file of buffer
void mergeToMono()
average all the channels to mono
virtual void readBufferFromFile(unsigned numFr)=0
virtual unsigned seekTo(int position, SeekPosition whence)=0
seek to some position relative to "whence"
virtual void setToEnd()
set to end position
virtual SampleBuffer buffer(unsigned bufNum)
convenience accessors for sample buffers
virtual void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
really compute the next buffer given an offset base channel; this is called by nextBuffer, possibly multiple times
virtual void setPath(string path)
set file name path string
Abst_SoundFile * mFile
the file I point into
void dump(void)
pretty-print me UGen operations
float mFloatCurrent
current pointer as a float
virtual void trigger()
reset to start
void copyFrom(Buffer &src)
void freeBuffers()
fcn to free them
The CSL system defaults class.
void setSize(unsigned numChannels, unsigned numFrames)
void setStopRatio(float val)
bool mIsValid
is my file valid?
Abst_SoundFile(string path, int start=-1, int stop=-1)
Constructor. Values not passed default to null.
#define kSoundFileFormatSND
void readFrom(FILE *input)
for loading file lists
bool isActive()
query whether I'm currently active (Envelopes can go inactive)
int mCurrent
the start/stop samples I represent
#define kSoundFileFormatOther
unsigned mCurrentFrame
where I currently am in the buffer
float sample
(could be changed to int, or double)
unsigned mNumChannels
my "expected" number of output channels
#define kSoundFileFormatWAV
virtual void freeBuffer()
free the file cache
virtual void openForRead(bool load=true)=0
Writeable – a mix-in for buffers and streams that one can write to.
void nextBuffer(Buffer &outputBuffer)
copy next buffer from cache
bool readTags()
read the ID3 or other tags. Returns true if able to read them.
static bool isSndfileName(const char *path)
Answer whether the given name looks like a snd file.
int mStop
starting/ending frames (or -1 if not used)
virtual void nextBuffer(Buffer &outB)
UGen operations are implemented here copy next buffer from file cache.
void setWaveform(Buffer &wave, bool freeBufs=true)
plug in waveforms set the interpolation flag
virtual SampleBuffer buffer(unsigned bufNum)
Buffer mWavetable
the stored wave form
void setStartRatio(float val)
#define CSL_WORD_LEN
default short string length
#define LOAD_SCALABLE_CONTROLS
Load the scale/offset-related values at the start.
bool mDidIAllocateBuffers
who allocated my data buffers?
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
virtual void dump()
log snd file props
void setStartSec(float val)
void convertRate(int fromRate, int toRate)
perform sample-rate conversion
void setRate(UnitGenerator &frequency)
set the receiver's playback rate (pitch ratio)
void allocateBuffers()
fcn to malloc storage buffers
SoundFileMetadata * mProperties
the ID3 tags properties
void addInput(CSL_MAP_KEY name, UnitGenerator &ugen)
Plug in a unit generator to the named input slot.
PortMap mInputs
the map of my inputs or controls (used by the mix-in classes)
void checkBuffer(unsigned numFrames)
allocate buffer lazily
virtual bool isCached()
answer if file is loaded into RAM
Here's the abstract sound file reader/writer class, a sample player UGen. The concrete subclasses rep...
unsigned channels() const
accessors
Seekable – a mix-in for positionable streams.
float durationInSecs()
number of frames in the sound file
Base class of CSL exceptions (written upper-case). Has a string message.
void setStopSec(float val)
#define DECLARE_SCALABLE_CONTROLS
Macros for all the Scalable UnitGenerators (note that these don't end with ";")