diff options
Diffstat (limited to 'extern/audaspace/bindings/C/AUD_Special.cpp')
-rw-r--r-- | extern/audaspace/bindings/C/AUD_Special.cpp | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/extern/audaspace/bindings/C/AUD_Special.cpp b/extern/audaspace/bindings/C/AUD_Special.cpp new file mode 100644 index 00000000000..f8f46651231 --- /dev/null +++ b/extern/audaspace/bindings/C/AUD_Special.cpp @@ -0,0 +1,420 @@ +/******************************************************************************* + * Copyright 2009-2016 Jörg Müller + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +#include "Exception.h" +#include "IReader.h" +#include "file/File.h" +#include "respec/ChannelMapper.h" +#include "fx/Lowpass.h" +#include "fx/Highpass.h" +#include "fx/Envelope.h" +#include "respec/LinearResample.h" +#include "fx/Threshold.h" +#include "fx/Accumulator.h" +#include "fx/Sum.h" +#include "generator/Silence.h" +#include "fx/Limiter.h" +#include "devices/DeviceManager.h" +#include "sequence/Sequence.h" +#include "file/FileWriter.h" +#include "devices/ReadDevice.h" +#include "plugin/PluginManager.h" +#include "devices/DeviceManager.h" +#include "devices/IDeviceFactory.h" +#include "devices/NULLDevice.h" + +#include <cassert> +#include <cstring> +#include <cmath> +#include <sstream> + +using namespace aud; + +#define AUD_CAPI_IMPLEMENTATION +#include "AUD_Special.h" + +static inline AUD_Specs convSpecToC(aud::Specs specs) +{ + AUD_Specs s; + s.channels = static_cast<AUD_Channels>(specs.channels); + s.rate = static_cast<AUD_SampleRate>(specs.rate); + return s; +} + +static inline aud::Specs convCToSpec(AUD_Specs specs) +{ + aud::Specs s; + s.channels = static_cast<Channels>(specs.channels); + s.rate = static_cast<SampleRate>(specs.rate); + return s; +} + +static inline AUD_DeviceSpecs convDSpecToC(aud::DeviceSpecs specs) +{ + AUD_DeviceSpecs s; + s.specs = convSpecToC(specs.specs); + s.format = static_cast<AUD_SampleFormat>(specs.format); + return s; +} + +static inline aud::DeviceSpecs convCToDSpec(AUD_DeviceSpecs specs) +{ + aud::DeviceSpecs s; + s.specs = convCToSpec(specs.specs); + s.format = static_cast<SampleFormat>(specs.format); + return s; +} + +AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) +{ + assert(sound); + + AUD_SoundInfo info; + info.specs.channels = AUD_CHANNELS_INVALID; + info.specs.rate = AUD_RATE_INVALID; + info.length = 0.0f; + + try + { + std::shared_ptr<IReader> reader = (*sound)->createReader(); + + if(reader.get()) + { + info.specs = convSpecToC(reader->getSpecs()); + info.length = reader->getLength() / (float) info.specs.rate; + } + } + catch(Exception&) + { + } + + return info; +} + +AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float high, + float attack, float release, float threshold, + int accumulate, int additive, int square, + float sthreshold, double samplerate, int* length) +{ + Buffer buffer; + DeviceSpecs specs; + specs.channels = CHANNELS_MONO; + specs.rate = (SampleRate)samplerate; + std::shared_ptr<ISound> sound; + + std::shared_ptr<ISound> file = std::shared_ptr<ISound>(new File(filename)); + + int position = 0; + + try + { + std::shared_ptr<IReader> reader = file->createReader(); + + SampleRate rate = reader->getSpecs().rate; + + sound = std::shared_ptr<ISound>(new ChannelMapper(file, specs)); + + if(high < rate) + sound = std::shared_ptr<ISound>(new Lowpass(sound, high)); + if(low > 0) + sound = std::shared_ptr<ISound>(new Highpass(sound, low)); + + sound = std::shared_ptr<ISound>(new Envelope(sound, attack, release, threshold, 0.1f)); + sound = std::shared_ptr<ISound>(new LinearResample(sound, specs)); + + if(square) + sound = std::shared_ptr<ISound>(new Threshold(sound, sthreshold)); + + if(accumulate) + sound = std::shared_ptr<ISound>(new Accumulator(sound, additive)); + else if(additive) + sound = std::shared_ptr<ISound>(new Sum(sound)); + + reader = sound->createReader(); + + if(!reader.get()) + return nullptr; + + int len; + bool eos; + do + { + len = samplerate; + buffer.resize((position + len) * sizeof(float), true); + reader->read(len, eos, buffer.getBuffer() + position); + position += len; + } while(!eos); + } + catch(Exception&) + { + return nullptr; + } + + float * result = (float *)malloc(position * sizeof(float)); + std::memcpy(result, buffer.getBuffer(), position * sizeof(float)); + *length = position; + return result; +} + +static void pauseSound(AUD_Handle* handle) +{ + assert(handle); + (*handle)->pause(); +} + +AUD_API AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds) +{ + std::shared_ptr<ISound> silence = std::shared_ptr<ISound>(new Silence); + std::shared_ptr<ISound> limiter = std::shared_ptr<ISound>(new Limiter(silence, 0, seconds)); + + auto device = DeviceManager::getDevice(); + + std::lock_guard<ILockable> lock(*device); + + try + { + AUD_Handle handle2 = device->play(limiter); + if(handle2.get()) + { + handle2->setStopCallback((stopCallback)pauseSound, handle); + return new AUD_Handle(handle2); + } + } + catch(Exception&) + { + } + + return nullptr; +} + +AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, int samples_per_second, short* interrupt) +{ + DeviceSpecs specs; + float* buf; + Buffer aBuffer; + + specs.rate = RATE_INVALID; + specs.channels = CHANNELS_MONO; + specs.format = FORMAT_INVALID; + + std::shared_ptr<IReader> reader = ChannelMapper(*sound, specs).createReader(); + + specs.specs = reader->getSpecs(); + int len; + float samplejump = specs.rate / samples_per_second; + float min, max, power, overallmax; + bool eos; + + overallmax = 0; + + for(int i = 0; i < length; i++) + { + len = floor(samplejump * (i+1)) - floor(samplejump * i); + + if(*interrupt) + return 0; + + aBuffer.assureSize(len * AUD_SAMPLE_SIZE(specs)); + buf = aBuffer.getBuffer(); + + reader->read(len, eos, buf); + + max = min = *buf; + power = *buf * *buf; + for(int j = 1; j < len; j++) + { + if(buf[j] < min) + min = buf[j]; + if(buf[j] > max) + max = buf[j]; + power += buf[j] * buf[j]; + } + + buffer[i * 3] = min; + buffer[i * 3 + 1] = max; + buffer[i * 3 + 2] = sqrt(power) / len; + + if(overallmax < max) + overallmax = max; + if(overallmax < -min) + overallmax = -min; + + if(eos) + { + length = i; + break; + } + } + + if(overallmax > 1.0f) + { + for(int i = 0; i < length * 3; i++) + { + buffer[i] /= overallmax; + } + } + + return length; +} + +AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) +{ + try + { + Sequence* f = dynamic_cast<Sequence *>(sound->get()); + + f->setSpecs(convCToSpec(specs.specs)); + std::shared_ptr<IReader> reader = f->createQualityReader(); + reader->seek(start); + std::shared_ptr<IWriter> writer = FileWriter::createWriter(filename, convCToDSpec(specs), static_cast<Container>(format), static_cast<Codec>(codec), bitrate); + FileWriter::writeReader(reader, writer, length, buffersize); + + return nullptr; + } + catch(Exception& e) + { + return e.getMessage().c_str(); + } +} + +AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) +{ + try + { + Sequence* f = dynamic_cast<Sequence *>(sound->get()); + + f->setSpecs(convCToSpec(specs.specs)); + + std::vector<std::shared_ptr<IWriter> > writers; + + int channels = specs.channels; + specs.channels = AUD_CHANNELS_MONO; + + for(int i = 0; i < channels; i++) + { + std::stringstream stream; + std::string fn = filename; + size_t index = fn.find_last_of('.'); + size_t index_slash = fn.find_last_of('/'); + size_t index_backslash = fn.find_last_of('\\'); + + if((index == std::string::npos) || + ((index < index_slash) && (index_slash != std::string::npos)) || + ((index < index_backslash) && (index_backslash != std::string::npos))) + { + stream << filename << "_" << (i + 1); + } + else + { + stream << fn.substr(0, index) << "_" << (i + 1) << fn.substr(index); + } + writers.push_back(FileWriter::createWriter(stream.str(), convCToDSpec(specs), static_cast<Container>(format), static_cast<Codec>(codec), bitrate)); + } + + std::shared_ptr<IReader> reader = f->createQualityReader(); + reader->seek(start); + FileWriter::writeReader(reader, writers, length, buffersize); + + return nullptr; + } + catch(Exception& e) + { + return e.getMessage().c_str(); + } +} + +AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start) +{ + try + { + ReadDevice* device = new ReadDevice(convCToDSpec(specs)); + device->setQuality(true); + device->setVolume(volume); + + Sequence* f = dynamic_cast<Sequence*>(sequencer->get()); + + f->setSpecs(convCToSpec(specs.specs)); + + AUD_Handle handle = device->play(f->createQualityReader()); + if(handle.get()) + { + handle->seek(start); + } + + return new AUD_Device(device); + } + catch(Exception&) + { + return nullptr; + } +} + +AUD_API void AUD_initOnce() +{ + PluginManager::loadPlugins(); + NULLDevice::registerPlugin(); +} + +AUD_API void AUD_exitOnce() +{ +} + +AUD_API AUD_Device* AUD_init(const char* device, AUD_DeviceSpecs specs, int buffersize, const char* name) +{ + try + { + std::shared_ptr<IDeviceFactory> factory = DeviceManager::getDeviceFactory(device); + + if(factory) + { + factory->setName(name); + factory->setBufferSize(buffersize); + factory->setSpecs(convCToDSpec(specs)); + auto device = factory->openDevice(); + DeviceManager::setDevice(device); + + return new AUD_Device(device); + } + } + catch(Exception&) + { + } + return nullptr; +} + +AUD_API void AUD_exit(AUD_Device* device) +{ + delete device; + DeviceManager::releaseDevice(); +} + + +AUD_API char** AUD_getDeviceNames() +{ + std::vector<std::string> v_names = DeviceManager::getAvailableDeviceNames(); + char** names = (char**) malloc(sizeof(char*) * (v_names.size() + 1)); + + for(int i = 0; i < v_names.size(); i++) + { + std::string name = v_names[i]; + names[i] = (char*) malloc(sizeof(char) * (name.length() + 1)); + strcpy(names[i], name.c_str()); + } + + names[v_names.size()] = nullptr; + + return names; +} |