mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-03 03:30:06 +00:00
Added the AudioData class, which contains a range of templated structrures for manipulating different sample type primitives. This will replace the old AudioDataConverters class, and I've refactored a lot of the audio devices and formats to use the new classes.
This commit is contained in:
parent
8f4aaa4873
commit
ba62157841
27 changed files with 1603 additions and 2510 deletions
|
|
@ -82,7 +82,7 @@ static void getDeviceProperties (const String& deviceID,
|
|||
if (snd_ctl_pcm_info (handle, info) >= 0)
|
||||
{
|
||||
snd_pcm_t* pcmHandle;
|
||||
if (snd_pcm_open (&pcmHandle, deviceID.toUTF8(), SND_PCM_STREAM_PLAYBACK, SND_PCM_ASYNC | SND_PCM_NONBLOCK ) >= 0)
|
||||
if (snd_pcm_open (&pcmHandle, deviceID.toUTF8(), SND_PCM_STREAM_PLAYBACK, SND_PCM_ASYNC | SND_PCM_NONBLOCK) >= 0)
|
||||
{
|
||||
getDeviceNumChannels (pcmHandle, &minChansOut, &maxChansOut);
|
||||
getDeviceSampleRates (pcmHandle, rates);
|
||||
|
|
@ -96,7 +96,7 @@ static void getDeviceProperties (const String& deviceID,
|
|||
if (snd_ctl_pcm_info (handle, info) >= 0)
|
||||
{
|
||||
snd_pcm_t* pcmHandle;
|
||||
if (snd_pcm_open (&pcmHandle, deviceID.toUTF8(), SND_PCM_STREAM_CAPTURE, SND_PCM_ASYNC | SND_PCM_NONBLOCK ) >= 0)
|
||||
if (snd_pcm_open (&pcmHandle, deviceID.toUTF8(), SND_PCM_STREAM_CAPTURE, SND_PCM_ASYNC | SND_PCM_NONBLOCK) >= 0)
|
||||
{
|
||||
getDeviceNumChannels (pcmHandle, &minChansIn, &maxChansIn);
|
||||
|
||||
|
|
@ -115,14 +115,12 @@ static void getDeviceProperties (const String& deviceID,
|
|||
class ALSADevice
|
||||
{
|
||||
public:
|
||||
ALSADevice (const String& deviceID,
|
||||
const bool forInput)
|
||||
ALSADevice (const String& deviceID, bool forInput)
|
||||
: handle (0),
|
||||
bitDepth (16),
|
||||
numChannelsRunning (0),
|
||||
latency (0),
|
||||
isInput (forInput),
|
||||
sampleFormat (AudioDataConverters::int16LE)
|
||||
isInput (forInput)
|
||||
{
|
||||
failed (snd_pcm_open (&handle, deviceID.toUTF8(),
|
||||
forInput ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
|
||||
|
|
@ -156,22 +154,26 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
const int formatsToTry[] = { SND_PCM_FORMAT_FLOAT_LE, 32, AudioDataConverters::float32LE,
|
||||
SND_PCM_FORMAT_FLOAT_BE, 32, AudioDataConverters::float32BE,
|
||||
SND_PCM_FORMAT_S32_LE, 32, AudioDataConverters::int32LE,
|
||||
SND_PCM_FORMAT_S32_BE, 32, AudioDataConverters::int32BE,
|
||||
SND_PCM_FORMAT_S24_3LE, 24, AudioDataConverters::int24LE,
|
||||
SND_PCM_FORMAT_S24_3BE, 24, AudioDataConverters::int24BE,
|
||||
SND_PCM_FORMAT_S16_LE, 16, AudioDataConverters::int16LE,
|
||||
SND_PCM_FORMAT_S16_BE, 16, AudioDataConverters::int16BE };
|
||||
enum { isFloatBit = 1 << 16, isLittleEndianBit = 1 << 17 };
|
||||
|
||||
const int formatsToTry[] = { SND_PCM_FORMAT_FLOAT_LE, 32 | isFloatBit | isLittleEndianBit,
|
||||
SND_PCM_FORMAT_FLOAT_BE, 32 | isFloatBit,
|
||||
SND_PCM_FORMAT_S32_LE, 32 | isLittleEndianBit,
|
||||
SND_PCM_FORMAT_S32_BE, 32,
|
||||
SND_PCM_FORMAT_S24_3LE, 24 | isLittleEndianBit,
|
||||
SND_PCM_FORMAT_S24_3BE, 24,
|
||||
SND_PCM_FORMAT_S16_LE, 16 | isLittleEndianBit,
|
||||
SND_PCM_FORMAT_S16_BE, 16 };
|
||||
bitDepth = 0;
|
||||
|
||||
for (int i = 0; i < numElementsInArray (formatsToTry); i += 3)
|
||||
for (int i = 0; i < numElementsInArray (formatsToTry); i += 2)
|
||||
{
|
||||
if (snd_pcm_hw_params_set_format (handle, hwParams, (_snd_pcm_format) formatsToTry [i]) >= 0)
|
||||
{
|
||||
bitDepth = formatsToTry [i + 1];
|
||||
sampleFormat = (AudioDataConverters::DataFormat) formatsToTry [i + 2];
|
||||
bitDepth = formatsToTry [i + 1] & 255;
|
||||
const bool isFloat = (formatsToTry [i + 1] & isFloatBit) != 0;
|
||||
const bool isLittleEndian = (formatsToTry [i + 1] & isLittleEndianBit) != 0;
|
||||
converter = createConverter (isInput, bitDepth, isFloat, isLittleEndian, numChannels);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -235,48 +237,44 @@ public:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
bool write (AudioSampleBuffer& outputChannelBuffer, const int numSamples)
|
||||
bool writeToOutputDevice (AudioSampleBuffer& outputChannelBuffer, const int numSamples)
|
||||
{
|
||||
jassert (numChannelsRunning <= outputChannelBuffer.getNumChannels());
|
||||
float** const data = outputChannelBuffer.getArrayOfChannels();
|
||||
snd_pcm_sframes_t numDone = 0;
|
||||
|
||||
if (isInterleaved)
|
||||
{
|
||||
scratch.ensureSize (sizeof (float) * numSamples * numChannelsRunning, false);
|
||||
float* interleaved = static_cast <float*> (scratch.getData());
|
||||
|
||||
AudioDataConverters::interleaveSamples ((const float**) data, interleaved, numSamples, numChannelsRunning);
|
||||
AudioDataConverters::convertFloatToFormat (sampleFormat, interleaved, interleaved, numSamples * numChannelsRunning);
|
||||
for (int i = 0; i < numChannelsRunning; ++i)
|
||||
converter->convertSamples (scratch.getData(), i, data[i], 0, numSamples);
|
||||
|
||||
snd_pcm_sframes_t num = snd_pcm_writei (handle, interleaved, numSamples);
|
||||
|
||||
if (failed (num) && num != -EPIPE && num != -ESTRPIPE)
|
||||
return false;
|
||||
numDone = snd_pcm_writei (handle, scratch.getData(), numSamples);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < numChannelsRunning; ++i)
|
||||
if (data[i] != 0)
|
||||
AudioDataConverters::convertFloatToFormat (sampleFormat, data[i], data[i], numSamples);
|
||||
converter->convertSamples (data[i], data[i], numSamples);
|
||||
|
||||
snd_pcm_sframes_t num = snd_pcm_writen (handle, (void**) data, numSamples);
|
||||
numDone = snd_pcm_writen (handle, (void**) data, numSamples);
|
||||
}
|
||||
|
||||
if (failed (num))
|
||||
if (failed (numDone))
|
||||
{
|
||||
if (numDone == -EPIPE)
|
||||
{
|
||||
if (num == -EPIPE)
|
||||
{
|
||||
if (failed (snd_pcm_prepare (handle)))
|
||||
return false;
|
||||
}
|
||||
else if (num != -ESTRPIPE)
|
||||
if (failed (snd_pcm_prepare (handle)))
|
||||
return false;
|
||||
}
|
||||
else if (numDone != -ESTRPIPE)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read (AudioSampleBuffer& inputChannelBuffer, const int numSamples)
|
||||
bool readFromInputDevice (AudioSampleBuffer& inputChannelBuffer, const int numSamples)
|
||||
{
|
||||
jassert (numChannelsRunning <= inputChannelBuffer.getNumChannels());
|
||||
float** const data = inputChannelBuffer.getArrayOfChannels();
|
||||
|
|
@ -284,9 +282,8 @@ public:
|
|||
if (isInterleaved)
|
||||
{
|
||||
scratch.ensureSize (sizeof (float) * numSamples * numChannelsRunning, false);
|
||||
float* interleaved = static_cast <float*> (scratch.getData());
|
||||
|
||||
snd_pcm_sframes_t num = snd_pcm_readi (handle, interleaved, numSamples);
|
||||
snd_pcm_sframes_t num = snd_pcm_readi (handle, scratch.getData(), numSamples);
|
||||
|
||||
if (failed (num))
|
||||
{
|
||||
|
|
@ -299,8 +296,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
AudioDataConverters::convertFormatToFloat (sampleFormat, interleaved, interleaved, numSamples * numChannelsRunning);
|
||||
AudioDataConverters::deinterleaveSamples (interleaved, data, numSamples, numChannelsRunning);
|
||||
for (int i = 0; i < numChannelsRunning; ++i)
|
||||
converter->convertSamples (data[i], 0, scratch.getData(), i, numSamples);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -310,8 +307,7 @@ public:
|
|||
return false;
|
||||
|
||||
for (int i = 0; i < numChannelsRunning; ++i)
|
||||
if (data[i] != 0)
|
||||
AudioDataConverters::convertFormatToFloat (sampleFormat, data[i], data[i], numSamples);
|
||||
converter->convertSamples (data[i], data[i], numSamples);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -329,7 +325,48 @@ private:
|
|||
const bool isInput;
|
||||
bool isInterleaved;
|
||||
MemoryBlock scratch;
|
||||
AudioDataConverters::DataFormat sampleFormat;
|
||||
ScopedPointer<AudioData::Converter> converter;
|
||||
|
||||
//==============================================================================
|
||||
template <class SampleType>
|
||||
struct ConverterHelper
|
||||
{
|
||||
static AudioData::Converter* createConverter (const bool forInput, const bool isLittleEndian, const int numInterleavedChannels)
|
||||
{
|
||||
if (forInput)
|
||||
{
|
||||
typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> DestType;
|
||||
|
||||
if (isLittleEndian)
|
||||
return new AudioData::ConverterInstance <AudioData::Pointer <SampleType, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, DestType> (numInterleavedChannels, 1);
|
||||
else
|
||||
return new AudioData::ConverterInstance <AudioData::Pointer <SampleType, AudioData::BigEndian, AudioData::Interleaved, AudioData::Const>, DestType> (numInterleavedChannels, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SourceType;
|
||||
|
||||
if (isLittleEndian)
|
||||
return new AudioData::ConverterInstance <SourceType, AudioData::Pointer <SampleType, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, numInterleavedChannels);
|
||||
else
|
||||
return new AudioData::ConverterInstance <SourceType, AudioData::Pointer <SampleType, AudioData::BigEndian, AudioData::Interleaved, AudioData::NonConst> > (1, numInterleavedChannels);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static AudioData::Converter* createConverter (const bool forInput, const int bitDepth, const bool isFloat, const bool isLittleEndian, const int numInterleavedChannels)
|
||||
{
|
||||
switch (bitDepth)
|
||||
{
|
||||
case 16: return ConverterHelper <AudioData::Int16>::createConverter (forInput, isLittleEndian, numInterleavedChannels);
|
||||
case 24: return ConverterHelper <AudioData::Int24>::createConverter (forInput, isLittleEndian, numInterleavedChannels);
|
||||
case 32: return isFloat ? ConverterHelper <AudioData::Float32>::createConverter (forInput, isLittleEndian, numInterleavedChannels)
|
||||
: ConverterHelper <AudioData::Int32>::createConverter (forInput, isLittleEndian, numInterleavedChannels);
|
||||
default: jassertfalse; break; // unsupported format!
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool failed (const int errorNum)
|
||||
|
|
@ -522,7 +559,7 @@ public:
|
|||
{
|
||||
if (inputDevice != 0)
|
||||
{
|
||||
if (! inputDevice->read (inputChannelBuffer, bufferSize))
|
||||
if (! inputDevice->readFromInputDevice (inputChannelBuffer, bufferSize))
|
||||
{
|
||||
DBG ("ALSA: read failure");
|
||||
break;
|
||||
|
|
@ -560,7 +597,7 @@ public:
|
|||
|
||||
failed (snd_pcm_avail_update (outputDevice->handle));
|
||||
|
||||
if (! outputDevice->write (outputChannelBuffer, bufferSize))
|
||||
if (! outputDevice->writeToOutputDevice (outputChannelBuffer, bufferSize))
|
||||
{
|
||||
DBG ("ALSA: write failure");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -279,10 +279,19 @@ END_JUCE_NAMESPACE
|
|||
|
||||
source->getNextAudioBlock (info);
|
||||
|
||||
JUCE_NAMESPACE::AudioDataConverters::convertFloatToInt16LE (tempBuffer.getSampleData (0),
|
||||
buffer, numSamples, 4);
|
||||
JUCE_NAMESPACE::AudioDataConverters::convertFloatToInt16LE (tempBuffer.getSampleData (1),
|
||||
buffer + 2, numSamples, 4);
|
||||
typedef JUCE_NAMESPACE::AudioData::Pointer <JUCE_NAMESPACE::AudioData::Int16,
|
||||
JUCE_NAMESPACE::AudioData::LittleEndian,
|
||||
JUCE_NAMESPACE::AudioData::Interleaved,
|
||||
JUCE_NAMESPACE::AudioData::NonConst> CDSampleFormat;
|
||||
|
||||
typedef JUCE_NAMESPACE::AudioData::Pointer <JUCE_NAMESPACE::AudioData::Float32,
|
||||
JUCE_NAMESPACE::AudioData::NativeEndian,
|
||||
JUCE_NAMESPACE::AudioData::NonInterleaved,
|
||||
JUCE_NAMESPACE::AudioData::Const> SourceSampleFormat;
|
||||
CDSampleFormat left (buffer, 2);
|
||||
left.convertSamples (SourceSampleFormat (tempBuffer.getSampleData (0)), numSamples);
|
||||
CDSampleFormat right (buffer + 2, 2);
|
||||
right.convertSamples (SourceSampleFormat (tempBuffer.getSampleData (1)), numSamples);
|
||||
|
||||
readPosition += numSamples;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,7 +306,6 @@ public:
|
|||
size = sizeof (lat);
|
||||
pa.mSelector = kAudioDevicePropertyLatency;
|
||||
pa.mScope = kAudioDevicePropertyScopeInput;
|
||||
//if (AudioDeviceGetProperty (deviceID, 0, true, kAudioDevicePropertyLatency, &size, &lat) == noErr)
|
||||
if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &lat) == noErr)
|
||||
inputLatency = (int) lat;
|
||||
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ private:
|
|||
}
|
||||
|
||||
// If we failed to find it "properly", this dodgy fall-back seems to do the trick for most fonts!
|
||||
return jmax (-1, c - 29);
|
||||
return jmax (-1, (int) c - 29);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ public:
|
|||
JUCEApplication::appWillTerminateByForce();
|
||||
}
|
||||
|
||||
virtual BOOL openFile (const NSString* filename)
|
||||
virtual BOOL openFile (NSString* filename)
|
||||
{
|
||||
if (JUCEApplication::getInstance() != 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2378,11 +2378,16 @@ bool AudioCDBurner::addAudioTrack (AudioSource* audioSource, int numSamples)
|
|||
|
||||
zeromem (buffer, bytesPerBlock);
|
||||
|
||||
AudioDataConverters::convertFloatToInt16LE (sourceBuffer.getSampleData (0, 0),
|
||||
buffer, samplesPerBlock, 4);
|
||||
typedef AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian,
|
||||
AudioData::Interleaved, AudioData::NonConst> CDSampleFormat;
|
||||
|
||||
AudioDataConverters::convertFloatToInt16LE (sourceBuffer.getSampleData (1, 0),
|
||||
buffer + 2, samplesPerBlock, 4);
|
||||
typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian,
|
||||
AudioData::NonInterleaved, AudioData::Const> SourceSampleFormat;
|
||||
|
||||
CDSampleFormat left (buffer, 2);
|
||||
left.convertSamples (SourceSampleFormat (sourceBuffer.getSampleData (0)), samplesPerBlock);
|
||||
CDSampleFormat right (buffer + 2, 2);
|
||||
right.convertSamples (SourceSampleFormat (sourceBuffer.getSampleData (1)), samplesPerBlock);
|
||||
|
||||
hr = pimpl->redbook->AddAudioTrackBlocks (buffer, bytesPerBlock);
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ DynamicLibraryLoader::~DynamicLibraryLoader()
|
|||
|
||||
void* DynamicLibraryLoader::findProcAddress (const String& functionName)
|
||||
{
|
||||
return GetProcAddress ((HMODULE) libHandle, functionName.toCString());
|
||||
return (void*) GetProcAddress ((HMODULE) libHandle, functionName.toCString()); // (void* cast is required for mingw)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ void PlatformUtilities::freeDynamicLibrary (void* h)
|
|||
|
||||
void* PlatformUtilities::getProcedureEntryPoint (void* h, const String& name)
|
||||
{
|
||||
return (h != 0) ? GetProcAddress ((HMODULE) h, name.toCString()) : 0;
|
||||
return (h != 0) ? (void*) GetProcAddress ((HMODULE) h, name.toCString()) : 0; // (void* cast is required for mingw)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -232,11 +232,12 @@ public:
|
|||
Array <double> rates;
|
||||
HANDLE clientEvent;
|
||||
BigInteger channels;
|
||||
AudioDataConverters::DataFormat dataFormat;
|
||||
Array <int> channelMaps;
|
||||
UINT32 actualBufferSize;
|
||||
int bytesPerSample;
|
||||
|
||||
virtual void updateFormat (bool isFloat) = 0;
|
||||
|
||||
private:
|
||||
const ComSmartPtr <IAudioClient> createClient()
|
||||
{
|
||||
|
|
@ -311,10 +312,8 @@ private:
|
|||
actualNumChannels = format.Format.nChannels;
|
||||
const bool isFloat = format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||
bytesPerSample = format.Format.wBitsPerSample / 8;
|
||||
dataFormat = isFloat ? AudioDataConverters::float32LE
|
||||
: (bytesPerSample == 4 ? AudioDataConverters::int32LE
|
||||
: ((bytesPerSample == 3 ? AudioDataConverters::int24LE
|
||||
: AudioDataConverters::int16LE)));
|
||||
|
||||
updateFormat (isFloat);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -356,6 +355,20 @@ public:
|
|||
reservoir.setSize (0);
|
||||
}
|
||||
|
||||
void updateFormat (bool isFloat)
|
||||
{
|
||||
typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> NativeType;
|
||||
|
||||
if (isFloat)
|
||||
converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Float32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1);
|
||||
else if (bytesPerSample == 4)
|
||||
converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Int32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1);
|
||||
else if (bytesPerSample == 3)
|
||||
converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Int24, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1);
|
||||
else
|
||||
converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1);
|
||||
}
|
||||
|
||||
void copyBuffers (float** destBuffers, int numDestBuffers, int bufferSize, Thread& thread)
|
||||
{
|
||||
if (numChannels <= 0)
|
||||
|
|
@ -370,31 +383,7 @@ public:
|
|||
const int samplesToDo = jmin (bufferSize, (int) reservoirSize);
|
||||
|
||||
for (int i = 0; i < numDestBuffers; ++i)
|
||||
{
|
||||
float* const dest = destBuffers[i] + offset;
|
||||
const int srcChan = channelMaps.getUnchecked(i);
|
||||
|
||||
switch (dataFormat)
|
||||
{
|
||||
case AudioDataConverters::float32LE:
|
||||
AudioDataConverters::convertFloat32LEToFloat (((uint8*) reservoir.getData()) + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels);
|
||||
break;
|
||||
|
||||
case AudioDataConverters::int32LE:
|
||||
AudioDataConverters::convertInt32LEToFloat (((uint8*) reservoir.getData()) + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels);
|
||||
break;
|
||||
|
||||
case AudioDataConverters::int24LE:
|
||||
AudioDataConverters::convertInt24LEToFloat (((uint8*) reservoir.getData()) + 3 * srcChan, dest, samplesToDo, 3 * actualNumChannels);
|
||||
break;
|
||||
|
||||
case AudioDataConverters::int16LE:
|
||||
AudioDataConverters::convertInt16LEToFloat (((uint8*) reservoir.getData()) + 2 * srcChan, dest, samplesToDo, 2 * actualNumChannels);
|
||||
break;
|
||||
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
}
|
||||
converter->convertSamples (destBuffers[i], offset, reservoir.getData(), channelMaps.getUnchecked(i), samplesToDo);
|
||||
|
||||
bufferSize -= samplesToDo;
|
||||
offset += samplesToDo;
|
||||
|
|
@ -424,31 +413,7 @@ public:
|
|||
const int samplesToDo = jmin (bufferSize, (int) numSamplesAvailable);
|
||||
|
||||
for (int i = 0; i < numDestBuffers; ++i)
|
||||
{
|
||||
float* const dest = destBuffers[i] + offset;
|
||||
const int srcChan = channelMaps.getUnchecked(i);
|
||||
|
||||
switch (dataFormat)
|
||||
{
|
||||
case AudioDataConverters::float32LE:
|
||||
AudioDataConverters::convertFloat32LEToFloat (inputData + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels);
|
||||
break;
|
||||
|
||||
case AudioDataConverters::int32LE:
|
||||
AudioDataConverters::convertInt32LEToFloat (inputData + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels);
|
||||
break;
|
||||
|
||||
case AudioDataConverters::int24LE:
|
||||
AudioDataConverters::convertInt24LEToFloat (inputData + 3 * srcChan, dest, samplesToDo, 3 * actualNumChannels);
|
||||
break;
|
||||
|
||||
case AudioDataConverters::int16LE:
|
||||
AudioDataConverters::convertInt16LEToFloat (inputData + 2 * srcChan, dest, samplesToDo, 2 * actualNumChannels);
|
||||
break;
|
||||
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
}
|
||||
converter->convertSamples (destBuffers[i], offset, inputData, channelMaps.getUnchecked(i), samplesToDo);
|
||||
|
||||
bufferSize -= samplesToDo;
|
||||
offset += samplesToDo;
|
||||
|
|
@ -469,6 +434,7 @@ public:
|
|||
ComSmartPtr <IAudioCaptureClient> captureClient;
|
||||
MemoryBlock reservoir;
|
||||
int reservoirSize, reservoirCapacity;
|
||||
ScopedPointer <AudioData::Converter> converter;
|
||||
|
||||
private:
|
||||
WASAPIInputDevice (const WASAPIInputDevice&);
|
||||
|
|
@ -501,6 +467,20 @@ public:
|
|||
renderClient = 0;
|
||||
}
|
||||
|
||||
void updateFormat (bool isFloat)
|
||||
{
|
||||
typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> NativeType;
|
||||
|
||||
if (isFloat)
|
||||
converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Float32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels);
|
||||
else if (bytesPerSample == 4)
|
||||
converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Int32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels);
|
||||
else if (bytesPerSample == 3)
|
||||
converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Int24, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels);
|
||||
else
|
||||
converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels);
|
||||
}
|
||||
|
||||
void copyBuffers (const float** const srcBuffers, const int numSrcBuffers, int bufferSize, Thread& thread)
|
||||
{
|
||||
if (numChannels <= 0)
|
||||
|
|
@ -530,31 +510,7 @@ public:
|
|||
if (OK (renderClient->GetBuffer (samplesToDo, &outputData)))
|
||||
{
|
||||
for (int i = 0; i < numSrcBuffers; ++i)
|
||||
{
|
||||
const float* const source = srcBuffers[i] + offset;
|
||||
const int destChan = channelMaps.getUnchecked(i);
|
||||
|
||||
switch (dataFormat)
|
||||
{
|
||||
case AudioDataConverters::float32LE:
|
||||
AudioDataConverters::convertFloatToFloat32LE (source, outputData + 4 * destChan, samplesToDo, 4 * actualNumChannels);
|
||||
break;
|
||||
|
||||
case AudioDataConverters::int32LE:
|
||||
AudioDataConverters::convertFloatToInt32LE (source, outputData + 4 * destChan, samplesToDo, 4 * actualNumChannels);
|
||||
break;
|
||||
|
||||
case AudioDataConverters::int24LE:
|
||||
AudioDataConverters::convertFloatToInt24LE (source, outputData + 3 * destChan, samplesToDo, 3 * actualNumChannels);
|
||||
break;
|
||||
|
||||
case AudioDataConverters::int16LE:
|
||||
AudioDataConverters::convertFloatToInt16LE (source, outputData + 2 * destChan, samplesToDo, 2 * actualNumChannels);
|
||||
break;
|
||||
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
}
|
||||
converter->convertSamples (outputData, channelMaps.getUnchecked(i), srcBuffers[i], offset, samplesToDo);
|
||||
|
||||
renderClient->ReleaseBuffer (samplesToDo, 0);
|
||||
|
||||
|
|
@ -565,6 +521,7 @@ public:
|
|||
}
|
||||
|
||||
ComSmartPtr <IAudioRenderClient> renderClient;
|
||||
ScopedPointer <AudioData::Converter> converter;
|
||||
|
||||
private:
|
||||
WASAPIOutputDevice (const WASAPIOutputDevice&);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue