/*
This file is part of Darling.
Copyright (C) 2020 Lubos Dolezel
Darling is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Darling is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Darling. If not, see .
*/
#include "AudioConverter.h"
#include "AudioConverterImpl.h"
#include
#include
#include
OSStatus AudioConverterNew(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat, AudioConverterRef* outAudioConverter)
{
return AudioConverter::create(inSourceFormat, inDestinationFormat, (AudioConverter**)outAudioConverter);
}
OSStatus AudioConverterNewSpecific(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat, UInt32 inNumberClassDescriptions, AudioClassDescription* nClassDescriptions, AudioConverterRef* outAudioConverter)
{
// FIXME
return AudioConverterNew(inSourceFormat, inDestinationFormat, outAudioConverter);
}
OSStatus AudioConverterReset(AudioConverterRef inAudioConverter)
{
if (inAudioConverter)
{
((AudioConverter*)inAudioConverter)->flush();
return noErr;
}
else
return paramErr;
}
OSStatus AudioConverterDispose(AudioConverterRef inAudioConverter)
{
delete (AudioConverter*)inAudioConverter;
return noErr;
}
OSStatus AudioConverterGetProperty(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 *ioPropertyDataSize, void *outPropertyData)
{
return ((AudioConverter*)inAudioConverter)->getProperty(inPropertyID, ioPropertyDataSize, outPropertyData);
}
OSStatus AudioConverterGetPropertyInfo(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable)
{
return ((AudioConverter*)inAudioConverter)->getPropertyInfo(inPropertyID, outSize, outWritable);
}
OSStatus AudioConverterSetProperty(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData)
{
return ((AudioConverter*)inAudioConverter)->setProperty(inPropertyID, inPropertyDataSize, inPropertyData);
}
OSStatus AudioConverterConvertBuffer(AudioConverterRef inAudioConverter, UInt32 inInputDataSize, const void* inInputData, UInt32 *ioOutputDataSize, void *outOutputData)
{
AudioBufferList in, out;
OSStatus stat;
in.mNumberBuffers = out.mNumberBuffers = 1;
in.mBuffers[0].mNumberChannels = 2;
out.mBuffers[0].mNumberChannels = 2;
in.mBuffers[0].mDataByteSize = inInputDataSize;
in.mBuffers[0].mData = const_cast(inInputData);
out.mBuffers[0].mDataByteSize = *ioOutputDataSize;
out.mBuffers[0].mData = outOutputData;
stat = AudioConverterConvertComplexBuffer(inAudioConverter, inInputDataSize/((AudioConverter*)inAudioConverter)->frameSize(), &in, &out);
*ioOutputDataSize = out.mBuffers[0].mDataByteSize;
return stat;
}
OSStatus AudioConverterFillComplexBuffer(AudioConverterRef inAudioConverter, AudioConverterComplexInputDataProc inInputDataProc, void *inInputDataProcUserData, UInt32 *ioOutputDataPacketSize, AudioBufferList *outOutputData, AudioStreamPacketDescription* outPacketDescription)
{
return ((AudioConverter*)inAudioConverter)->fillComplex(inInputDataProc, inInputDataProcUserData, ioOutputDataPacketSize, outOutputData, outPacketDescription);
}
OSStatus AudioConverterConvertComplexBuffer(AudioConverterRef inAudioConverter, UInt32 inNumberPCMFrames, const AudioBufferList *inInputData, AudioBufferList *outOutputData)
{
OSStatus status;
UInt32 dataPacketSize;
int64_t totalOutBytes = 0;
typedef OSStatus (^CallbackBlock)(AudioConverterRef audioConverter, UInt32* numberDataPackets, AudioBufferList* data, AudioStreamPacketDescription** dataPacketDescription);
CallbackBlock callbackBlock =
^ OSStatus (AudioConverterRef audioConverter, UInt32* numberDataPackets, AudioBufferList* data, AudioStreamPacketDescription** dataPacketDescription)
{
const AudioBufferList *inInputData = (AudioBufferList*) inInputData;
if (dataPacketDescription)
*dataPacketDescription = nullptr;
// TODO
return unimpErr;
};
// Squeezing a block through a function pointer
AudioConverterComplexInputDataProc proc = [](AudioConverterRef audioConverter, UInt32* numberDataPackets, AudioBufferList* data, AudioStreamPacketDescription** dataPacketDescription, void* userData) -> OSStatus
{
CallbackBlock callbackBlock = (CallbackBlock) userData;
return callbackBlock(audioConverter, numberDataPackets, data, dataPacketDescription);
};
for (UInt32 i = 0; i < outOutputData->mNumberBuffers; i++)
totalOutBytes += outOutputData->mBuffers[i].mDataByteSize;
dataPacketSize = totalOutBytes / ((AudioConverter*)inAudioConverter)->frameSize();
status = AudioConverterFillComplexBuffer(inAudioConverter, proc, (void*) inInputData, &dataPacketSize, outOutputData, nullptr);
return status;
}