diff options
Diffstat (limited to 'source/audio')
| -rw-r--r-- | source/audio/AudioSettings.c | 242 | ||||
| -rw-r--r-- | source/audio/AudioSettings.h | 183 | ||||
| -rw-r--r-- | source/audio/SampleBuffer.c | 175 | ||||
| -rw-r--r-- | source/audio/SampleBuffer.h | 107 |
4 files changed, 707 insertions, 0 deletions
diff --git a/source/audio/AudioSettings.c b/source/audio/AudioSettings.c new file mode 100644 index 0000000..7d47ec4 --- /dev/null +++ b/source/audio/AudioSettings.c @@ -0,0 +1,242 @@ +// +// AudioSettings.c - MrsWatson +// Created by Nik Reiman on 1/4/12. +// Copyright (c) 2012 Teragon Audio. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "audio/AudioSettings.h" +#include "logging/EventLogger.h" + +AudioSettings audioSettingsInstance = NULL; + +void initAudioSettings(void) +{ + if (audioSettingsInstance != NULL) { + freeAudioSettings(); + } + + audioSettingsInstance = malloc(sizeof(AudioSettingsMembers)); + audioSettingsInstance->sampleRate = DEFAULT_SAMPLE_RATE; + audioSettingsInstance->numChannels = DEFAULT_NUM_CHANNELS; + audioSettingsInstance->blocksize = DEFAULT_BLOCKSIZE; + audioSettingsInstance->tempo = DEFAULT_TEMPO; + audioSettingsInstance->timeSignatureBeatsPerMeasure = DEFAULT_TIMESIG_BEATS_PER_MEASURE; + audioSettingsInstance->timeSignatureNoteValue = DEFAULT_TIMESIG_NOTE_VALUE; +} + +static AudioSettings _getAudioSettings(void) +{ + if (audioSettingsInstance == NULL) { + initAudioSettings(); + } + + return audioSettingsInstance; +} + +SampleRate getSampleRate(void) +{ + return _getAudioSettings()->sampleRate; +} + +ChannelCount getNumChannels(void) +{ + return _getAudioSettings()->numChannels; +} + +SampleCount getBlocksize(void) +{ + return _getAudioSettings()->blocksize; +} + +Tempo getTempo(void) +{ + return _getAudioSettings()->tempo; +} + +unsigned short getTimeSignatureBeatsPerMeasure(void) +{ + return _getAudioSettings()->timeSignatureBeatsPerMeasure; +} + +unsigned short getTimeSignatureNoteValue(void) +{ + return _getAudioSettings()->timeSignatureNoteValue; +} + + +boolByte setSampleRate(const SampleRate sampleRate) +{ + if (sampleRate <= 0.0f) { + logError("Can't set sample rate to %f", sampleRate); + return false; + } + + logInfo("Setting sample rate to %gHz", sampleRate); + _getAudioSettings()->sampleRate = sampleRate; + return true; +} + +boolByte setNumChannels(const ChannelCount numChannels) +{ + if (numChannels <= 0) { + logError("Can't set channel count to %d", numChannels); + return false; + } + + logInfo("Setting %d channels", numChannels); + _getAudioSettings()->numChannels = numChannels; + return true; +} + +boolByte setBlocksize(const SampleCount blocksize) +{ + if (blocksize <= 0) { + logError("Can't set invalid blocksize %d", blocksize); + return false; + } + + logInfo("Setting blocksize to %ld", blocksize); + _getAudioSettings()->blocksize = blocksize; + return true; +} + + +boolByte setTempo(const Tempo tempo) +{ + if (tempo <= 0.0f) { + logError("Cannot set tempo to %f", tempo); + return false; + } + + //here + logInfo("NOT more Setting tempo to %f", tempo); + _getAudioSettings()->tempo = tempo; + return true; +} + +void setTempoFromMidiBytes(const byte *bytes) +{ + double tempo; + unsigned long beatLengthInMicroseconds = 0; + + printf("inside midi bytes function"); + if (bytes != NULL) { + float tempotest = getTempo(); + //seem like a good way to test it? yep + printf ("THIS WAS THE TEMPO: %f", tempotest); + if (!getTempo()){ //something like this? not sure how to tell if a struct is empty it's integer + logInfo("tempo was empty so setting to default value"); + beatLengthInMicroseconds = (unsigned long)(0x00000000 | (bytes[0] << 16) | (bytes[1] << 8) | (bytes[2])); + // Convert beats / microseconds -> beats / minutes + + tempo = (1000000.0 / (double)beatLengthInMicroseconds) * 60.0; + tempo = 120; //(1000000.0 / (double)2000) * 60.0; + //i guess this function just not called at all yeah but where is tempo Set then? default of some kind + //almost like this file isn't getting compiled. above I set tempo to 120, not 100 it might be not calling this function because bytes == NULL + //something like this? yes + setTempo((float)tempo); + }else{ + logInfo("Using tempo from command line args"); + }// so midi doesn't have tempo setting i guess t's setting to 100 now, it is supplied from cli? no + }else{ + logInfo("bytes == NULL"); + }// so midi doesn't have tempo setting i guess t's setting to 100 now, it is supplied from cli? no +} + +boolByte setTimeSignatureBeatsPerMeasure(const unsigned short beatsPerMeasure) +{ + // Bit of an easter egg :) + if (beatsPerMeasure < 2 || beatsPerMeasure > 12) { + logInfo("Freaky time signature, but whatever you say..."); + } + + if (beatsPerMeasure <= 0) { + logError("Ignoring attempt to set time signature numerator to %d", beatsPerMeasure); + return false; + } + + _getAudioSettings()->timeSignatureBeatsPerMeasure = beatsPerMeasure; + return true; +} + +boolByte setTimeSignatureNoteValue(const unsigned short noteValue) +{ + // Bit of an easter egg :) + if (!(noteValue == 2 || noteValue == 4 || noteValue == 8 || noteValue == 16) || noteValue < 2 || noteValue > 16) { + logInfo("Interesting time signature you've chosen. I'm sure this piece is going to sound great..."); + } + + if (noteValue <= 0) { + logError("Ignoring attempt to set time signature denominator to %d", noteValue); + return false; + } + + _getAudioSettings()->timeSignatureNoteValue = noteValue; + return true; +} + +boolByte setTimeSignatureFromString(const CharString signature) +{ + char *slash = NULL; + unsigned short numerator = 0; + unsigned short denominator = 0; + + if (!charStringIsEmpty(signature)) { + slash = strchr(signature->data, '/'); + + if (slash != NULL) { + *slash = '\0'; + numerator = (unsigned short)strtod(signature->data, NULL); + denominator = (unsigned short)strtod(slash + 1, NULL); + + if (numerator > 0 && denominator > 0) { + return (boolByte)(setTimeSignatureBeatsPerMeasure(numerator) && + setTimeSignatureNoteValue(denominator)); + } + } + } + + return false; +} + +boolByte setTimeSignatureFromMidiBytes(const byte *bytes) +{ + if (bytes != NULL) { + return (boolByte)(setTimeSignatureBeatsPerMeasure(bytes[0]) && + setTimeSignatureNoteValue((unsigned const short)powl(2, bytes[1]))); + } + + return false; +} + +void freeAudioSettings(void) +{ + free(audioSettingsInstance); + audioSettingsInstance = NULL; +} diff --git a/source/audio/AudioSettings.h b/source/audio/AudioSettings.h new file mode 100644 index 0000000..5d050f2 --- /dev/null +++ b/source/audio/AudioSettings.h @@ -0,0 +1,183 @@ +// +// AudioSettings.h - MrsWatson +// Created by Nik Reiman on 1/4/12. +// Copyright (c) 2012 Teragon Audio. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef MrsWatson_AudioSettings_h +#define MrsWatson_AudioSettings_h + +#include "base/Types.h" +#include "base/CharString.h" + +#define DEFAULT_SAMPLE_RATE 44100.0f +#define DEFAULT_NUM_CHANNELS 2 +#define DEFAULT_BLOCKSIZE 512l +#define DEFAULT_TIME_DIVISION 96 +#define DEFAULT_BITRATE 16 +#define DEFAULT_TEMPO 120.0f +#define DEFAULT_TIMESIG_BEATS_PER_MEASURE 4 +#define DEFAULT_TIMESIG_NOTE_VALUE 4 + +typedef struct { + SampleRate sampleRate; + ChannelCount numChannels; + SampleCount blocksize; + Tempo tempo; + unsigned short timeSignatureBeatsPerMeasure; + unsigned short timeSignatureNoteValue; +} AudioSettingsMembers; + +typedef AudioSettingsMembers *AudioSettings; +extern AudioSettings audioSettingsInstance; + +/** + * Initialize the global audio settings instance. Since many different classes + * require quick access to the audio settings, this is one of the few classes + * that has a global singleton instance rather than a "new" allocator. + */ +void initAudioSettings(void); + +/** + * Get the current sample rate. + * @return Sample rate in Hertz + */ +SampleRate getSampleRate(void); + +/** + * Get the number of output channels. + * @return Number of channels + */ +ChannelCount getNumChannels(void); + +/** + * Give the current block size, which is the number of sample frames sent to the + * plugin each time process is called. Note that the blocksize is the number of + * *frames* sent to the plugin, so if the channel count is 2 and the blocksize + * is 512, 1024 samples will be sent to the plugin. However in that case this + * function would still return 512. + * @return Blocksize, in sample frames + */ +SampleCount getBlocksize(void); + +/** + * Get the current tempo, in beats per minute + * @return Temo in BPM + */ +Tempo getTempo(void); + +/** + * Get the current time signature's numerator, the number of beats per measure. + * @return Time signature numerator + */ +unsigned short getTimeSignatureBeatsPerMeasure(void); + +/** + * Get the current time signatures denominator, the value of one beat unit. + * @return Time signature denominator + */ +unsigned short getTimeSignatureNoteValue(void); + +/** + * Set the sample rate to be used during processing. This must be set before the + * plugin chain is initialized. This function only requires a nonzero value, + * however some plugins may behave strangely when sent unusual sample rates. + * @param sampleRate Sample rate, in Hertz + * @return True if successfully set, false otherwise + */ +boolByte setSampleRate(const SampleRate sampleRate); + +/** + * Set the number of channels to be used during processing. Note that if the + * input source defines a channel called, it may override this value. + * @param numChannels Number of channels + * @return True if successfully set, false otherwise + */ +boolByte setNumChannels(const ChannelCount numChannels); + +/** + * Set the blocksize to be used during processing. Again this should be called + * before initializing the plugin chain. + * @param blocksize Blocksize in sample frames + * @return True if successfully set, false otherwise + */ +boolByte setBlocksize(const SampleCount blocksize); + +/** + * Set tempo to be used during processing. + * @param tempo Tempo in beats per minute + * @return True if successfully set, false otherwise + */ +boolByte setTempo(const Tempo tempo); + +/** + * MIDI files represent tempo in meta events with a three-byte payload. This + * method transforms the three byte sequence from such file into an actual tempo + * in beats per minute, and then sets the global tempo to this value. + * @param bytes Three byte sequence as read from a MIDI file + */ +void setTempoFromMidiBytes(const byte *bytes); + +/** + * Set the time signature's numerator. This function does very little error + * checking, but it does require a non-zero value. However, many plugins may act + * strangely with unusual time signatures. + * @param beatsPerMeasure Time signature numerator + * @return True if successfully set, false otherwise + */ +boolByte setTimeSignatureBeatsPerMeasure(const unsigned short beatsPerMeasure); + +/** + * Set the time signature's denominator. This function does very little error + * checking, but it does require a non-zero value. However, many plugins may act + * strangely with unusual time signatures. + * @param noteValue Time signature denominator + * @return True if successfully set, false otherwise + */ +boolByte setTimeSignatureNoteValue(const unsigned short noteValue); + +/** + * MIDI files represent musical time signature with a two-byte sequence. This + * function takes two bytes, derives the corresponding time signature, and sets + * it in the global instance. + * @param bytes Two byte sequence as read from a MIDI file + * @return True if successfully set, false otherwise + */ +boolByte setTimeSignatureFromMidiBytes(const byte *bytes); + +/** + * Set the time signature from a string, should look like "3/4". + * @param signature Time signature to set + * @return True if successfully set, false otherwise + */ +boolByte setTimeSignatureFromString(const CharString signature); + +/** + * Release memory of the global audio settings instance. Any attempt to use the + * audio settings functions after this has been called will result in undefined + * behavior. + */ +void freeAudioSettings(void); + +#endif diff --git a/source/audio/SampleBuffer.c b/source/audio/SampleBuffer.c new file mode 100644 index 0000000..610cd95 --- /dev/null +++ b/source/audio/SampleBuffer.c @@ -0,0 +1,175 @@ +// +// SampleBuffer.c - MrsWatson +// Created by Nik Reiman on 1/2/12. +// Copyright (c) 2012 Teragon Audio. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "audio/AudioSettings.h" +#include "audio/SampleBuffer.h" +#include "base/Endian.h" +#include "logging/EventLogger.h" +#include "SampleBuffer.h" + +SampleBuffer newSampleBuffer(ChannelCount numChannels, SampleCount blocksize) +{ + SampleBuffer sampleBuffer = (SampleBuffer)malloc(sizeof(SampleBufferMembers)); + sampleBuffer->numChannels = numChannels; + sampleBuffer->blocksize = blocksize; + sampleBuffer->samples = (Samples *)malloc(sizeof(Samples) * numChannels); + + for (ChannelCount i = 0; i < numChannels; i++) { + sampleBuffer->samples[i] = (Samples)malloc(sizeof(Sample) * blocksize); + } + + sampleBufferClear(sampleBuffer); + return sampleBuffer; +} + +void sampleBufferClear(SampleBuffer self) +{ + for (ChannelCount i = 0; i < self->numChannels; i++) { + memset(self->samples[i], 0, sizeof(Sample) * self->blocksize); + } +} + +boolByte sampleBufferCopyAndMapChannelsWithOffset(SampleBuffer destinationBuffer, + SampleCount destinationOffset, + const SampleBuffer sourceBuffer, + SampleCount sourceOffset, + SampleCount numberOfFrames) +{ + // Definitely not supported. + if (destinationBuffer->blocksize < destinationOffset + numberOfFrames) { + logInternalError("Destination buffer size %d < %d", destinationBuffer->blocksize, destinationOffset + numberOfFrames); + return false; + } + + // Definitely not supported. + if (sourceBuffer->blocksize < sourceOffset + numberOfFrames) { + logInternalError("Source buffer size %d < %d", sourceBuffer->blocksize, sourceOffset + numberOfFrames); + return false; + } + + if (sourceBuffer->numChannels != destinationBuffer->numChannels) { + logDebug("Mapping channels from %d -> %d", sourceBuffer->numChannels, destinationBuffer->numChannels); + } + + // If the other buffer is bigger (or the same size) as this buffer, then only + // copy up to the channel count of this buffer. Any other data will be lost, + // sorry about that! + if (sourceBuffer->numChannels >= destinationBuffer->numChannels) { + for (ChannelCount i = 0; i < destinationBuffer->numChannels; ++i) { + memcpy(destinationBuffer->samples[i] + destinationOffset, sourceBuffer->samples[i] + sourceOffset, sizeof(Sample) * numberOfFrames); + } + } + // But if this buffer is bigger than the other buffer, then copy all channels + // to this one. For example, if this buffer is 4 channels and the other buffer + // is 2 channels, then we copy the stereo pair to this channel (L R L R). + else { + for (ChannelCount i = 0; i < destinationBuffer->numChannels; ++i) { + if (sourceBuffer->numChannels > 0) { + memcpy(destinationBuffer->samples[i] + destinationOffset, + sourceBuffer->samples[i % sourceBuffer->numChannels] + sourceOffset, + sizeof(Sample) * numberOfFrames); + } else { + // If the other buffer has zero channels just clear this buffer. + memset(destinationBuffer->samples[i] + destinationOffset, 0, sizeof(Sample) * numberOfFrames); + } + } + } + + return true; +} + +boolByte sampleBufferCopyAndMapChannels(SampleBuffer self, const SampleBuffer buffer) +{ + // Definitely not supported, otherwise it would be hard to deal with partial + // copies and so forth. + if (self->blocksize != buffer->blocksize) { + logInternalError("Source and destination buffer are not the same size"); + return false; + } + + return sampleBufferCopyAndMapChannelsWithOffset(self, 0, buffer, 0, self->blocksize); +} + +void sampleBufferCopyPcmSamples(SampleBuffer self, const short *inPcmSamples) +{ + const unsigned int numChannels = self->numChannels; + const unsigned long numInterlacedSamples = numChannels * self->blocksize; + unsigned int currentInterlacedSample = 0; + unsigned int currentDeinterlacedSample = 0; + unsigned int currentChannel; + + while (currentInterlacedSample < numInterlacedSamples) { + for (currentChannel = 0; currentChannel < numChannels; ++currentChannel) { + Sample convertedSample = (Sample)inPcmSamples[currentInterlacedSample++] / 32767.0f; + self->samples[currentChannel][currentDeinterlacedSample] = convertedSample; + } + + ++currentDeinterlacedSample; + } +} + +void sampleBufferGetPcmSamples(const SampleBuffer self, short *outPcmSamples, boolByte flipEndian) +{ + const unsigned long blocksize = self->blocksize; + const unsigned int numChannels = self->numChannels; + unsigned int currentInterlacedSample = 0; + unsigned int currentSample = 0; + unsigned int currentChannel = 0; + short shortValue; + Sample sample; + + for (currentSample = 0; currentSample < blocksize; ++currentSample) { + for (currentChannel = 0; currentChannel < numChannels; ++currentChannel) { + sample = self->samples[currentChannel][currentSample]; + shortValue = (short)(sample * 32767.0f); + + if (flipEndian) { + outPcmSamples[currentInterlacedSample++] = flipShortEndian(shortValue); + } else { + outPcmSamples[currentInterlacedSample++] = shortValue; + } + } + } +} + +void freeSampleBuffer(SampleBuffer self) +{ + if (self == NULL) { + return; + } + + for (ChannelCount channel = 0; channel < self->numChannels; ++channel) { + free(self->samples[channel]); + } + free(self->samples); + free(self); +} diff --git a/source/audio/SampleBuffer.h b/source/audio/SampleBuffer.h new file mode 100644 index 0000000..7c19dc9 --- /dev/null +++ b/source/audio/SampleBuffer.h @@ -0,0 +1,107 @@ +// +// SampleBuffer.h - MrsWatson +// Created by Nik Reiman on 1/2/12. +// Copyright (c) 2012 Teragon Audio. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef MrsWatson_SampleBuffer_h +#define MrsWatson_SampleBuffer_h + +#include "base/Types.h" + +typedef struct { + ChannelCount numChannels; + SampleCount blocksize; + Samples *samples; +} SampleBufferMembers; +typedef SampleBufferMembers *SampleBuffer; + +/** + * Create a new SampleBuffer instance + * @param numChannels Number of channels + * @param blocksize Processing blocksize to use + * @return An initialized SampleBuffer instance + */ +SampleBuffer newSampleBuffer(ChannelCount numChannels, SampleCount blocksize); + +/** + * Set all samples to zero + * @param self + */ +void sampleBufferClear(SampleBuffer self); + +/** + * Copy some samples from another buffer to this one + * @param destinationBuffer + * @param destinationOffset zero-based index of where to start in destinationBuffer. + * @param sourceBuffer Other buffer to copy from + * @param sourceOffset zero-based index of where to start in buffer. + * @param numberOfFrames number of frames to copy. + * @return True on success, false on failure + */ +boolByte sampleBufferCopyAndMapChannelsWithOffset(SampleBuffer destinationBuffer, + SampleCount destinationOffset, + const SampleBuffer sourceBuffer, + SampleCount sourceOffset, + SampleCount numberOfFrames); + +/** +* Copy all samples from another buffer to this one +* @param self +* @param buffer Other buffer to copy from +* @return True on success, false on failure +*/ +boolByte sampleBufferCopyAndMapChannels(SampleBuffer self, const SampleBuffer buffer); + +/** + * Copy a buffer of interlaced short integer samples to a sample buffer. This + * function also converts the samples from integers to floating-point numbers. + * Mostly useful for reading raw PCM data into a format usable by plugins. + * @param self + * @param inPcmSamples Array of interlaced samples. Note that the size of the + * length of this array must match the SampleBuffer's blocksize * channel count, + * or else undefined behavior will occur. + */ +void sampleBufferCopyPcmSamples(SampleBuffer self, const short *inPcmSamples); + +/** + * Get an array of interlaced short integer samples from the SampleBuffer. This + * function will also convert the samples from floating-point numbers to short + * integers. Mostly useful for writing raw PCM data. + * @param self + * @param outPcmSamples A pre-allocated array large enough to hold the result of + * the conversion. This means that at least blocksize * channel count samples + * must be allocated + * @param flipEndian True if the output data should have the samples flipped + * from the native endianness. + */ +void sampleBufferGetPcmSamples(const SampleBuffer self, short *outPcmSamples, boolByte flipEndian); + +/** + * Free all memory used by a SampleBuffer instance + * @param sampleBuffer + */ +void freeSampleBuffer(SampleBuffer self); + +#endif |
