ez_audio 0.1.6

🔊 A easy to use audio playback library
#include "AudioInterface.h"

extern "C" AudioContext init(void (*end_callback)(void*)) {
	std::lock_guard<std::mutex> lock(global);
	ma_context* context = new ma_context();
	if(ma_context_init(NULL, 0, NULL, context) != MA_SUCCESS){
		std::cout << "Failed to initialize context" << std::endl;
		delete context;
		return AudioContext{nullptr, nullptr, false, nullptr};
	}

	endCallback = end_callback;

	return AudioContext{context, new std::unordered_map<size_t, SoundClip*>, true, new std::mutex()};
}

extern "C" void uninit(AudioContext* context) {
	std::lock_guard<std::mutex> lock(global);
	delete context->soundClips;
	ma_context_uninit(context->context);
	delete context->mtx;
}

extern "C" void setVolume(size_t id, AudioContext* context, float value) {
	context->soundClips->at(id)->device.masterVolumeFactor = value;
}

extern "C" float getVolume(size_t id, AudioContext* context) {
	return context->soundClips->at(id)->device.masterVolumeFactor;
}

extern "C" void play(size_t id, AudioContext* context){
	if(!ma_device_is_started(&context->soundClips->at(id)->device)){
		if(ma_device_start(&context->soundClips->at(id)->device) != MA_SUCCESS) {
			std::cout << "Failed to start playback" << std::endl;
		}
	}
}

extern "C" void reset(size_t id, AudioContext* context) {
	std::lock_guard<std::mutex> lock(context->soundClips->at(id)->mtx);
	ma_device_stop(&context->soundClips->at(id)->device);
	ma_decoder_seek_to_pcm_frame(&context->soundClips->at(id)->decoder, 0);
}

extern "C" void stop(size_t id, AudioContext* context) {
	ma_device_stop(&context->soundClips->at(id)->device);
}

extern "C" int load(size_t id, AudioContext* context, const char* path, AudioDevice* device) {
	SoundClip* soundClip = new SoundClip;
	soundClip->id = id;
	soundClip->audioDevice = device;
	soundClip->outer = nullptr;

	//creating and configuring decoder
	if(ma_decoder_init_file(path, NULL, &soundClip->decoder) != MA_SUCCESS) {
		ma_decoder_uninit(&soundClip->decoder);
		delete soundClip;
		return -1;
	}

	//configure device
	soundClip->deviceConfig = ma_device_config_init(ma_device_type_playback);
	soundClip->deviceConfig.playback.format   = soundClip->decoder.outputFormat;
	soundClip->deviceConfig.playback.channels = soundClip->decoder.outputChannels;
	soundClip->deviceConfig.sampleRate        = soundClip->decoder.outputSampleRate;
	soundClip->deviceConfig.dataCallback      = data_callback;
	soundClip->deviceConfig.pUserData         = soundClip;

	soundClip->deviceConfig.playback.pDeviceID = &device->id;

	if(ma_device_init(context->context, &soundClip->deviceConfig, &soundClip->device) != MA_SUCCESS) {
		std::cout << "Failed to open playback device" << std::endl;
		ma_decoder_uninit(&soundClip->decoder);
		delete soundClip;
		return -2;
	}

	soundClip->device.masterVolumeFactor = 1;

	std::lock_guard<std::mutex> lock(*context->mtx);
	context->soundClips->insert({id, soundClip});

	return 0;
}

extern "C" void setOuter(size_t id, AudioContext* context, void* outer) {
	std::lock_guard<std::mutex> lock(*context->mtx);
	context->soundClips->at(id)->outer = outer;
}

extern "C" void removeSound(size_t id, AudioContext* context){
	std::lock_guard<std::mutex> ctx_lock(*context->mtx);
	std::lock_guard<std::mutex> lock(context->soundClips->at(id)->mtx);
	ma_decoder_uninit(&context->soundClips->at(id)->decoder);
	ma_device_uninit(&context->soundClips->at(id)->device);
	
	delete context->soundClips->at(id)->device.pUserData;
	context->soundClips->erase(id);
}


extern "C" size_t getAudioDevices(AudioContext* context, AudioDevice* devices, size_t capacity) {
	ma_device_info* playbackDeviceInfos;
	ma_uint32 playbackDeviceCount;

	if(ma_context_get_devices(context->context, &playbackDeviceInfos, &playbackDeviceCount, NULL, NULL) != MA_SUCCESS) {
		std::cout << "Failed to retrieve device information" << std::endl;
		return 0;
	}
	
	ma_uint32 i{0};
	for (; i < playbackDeviceCount && i < capacity; ++i) {
		devices[i] = AudioDevice{
			playbackDeviceInfos[i].id,
			playbackDeviceInfos[i].name
		};
	}
	return i;
}

extern "C" size_t getAudioDeviceCount(AudioContext* context){
	ma_uint32 playbackDeviceCount;
	if(ma_context_get_devices(context->context, NULL, &playbackDeviceCount, NULL, NULL) != MA_SUCCESS) {
		std::cout << "Failed to retrieve device information" << std::endl;
		return 0;
	}
	return playbackDeviceCount;
}

extern "C" void setAudioDevice(size_t id, AudioContext* context, AudioDevice* device){
	std::lock_guard<std::mutex> lock(context->soundClips->at(id)->mtx);
	ma_device_uninit(&context->soundClips->at(id)->device);
	context->soundClips->at(id)->audioDevice = device;
	context->soundClips->at(id)->deviceConfig.playback.pDeviceID = &device->id;
	ma_device_init(context->context, &context->soundClips->at(id)->deviceConfig, &context->soundClips->at(id)->device);
}

extern "C" AudioDevice getDefaultAudioDevice(AudioContext* context){
	ma_device_info* playbackDeviceInfos;
	ma_uint32 playbackDeviceCount;
	if(ma_context_get_devices(context->context, &playbackDeviceInfos, &playbackDeviceCount, NULL, NULL) != MA_SUCCESS) {
		std::cout << "Failed to retrieve device information" << std::endl;
	}
	for(size_t i{0}; i<playbackDeviceCount; ++i){
		if(playbackDeviceInfos[i].isDefault) {
			return AudioDevice{
				playbackDeviceInfos[i].id,
				playbackDeviceInfos[i].name
			};
		}
	}
	return AudioDevice{
		playbackDeviceInfos[0].id,
		playbackDeviceInfos[0].name
	};
}

extern "C" uint64_t getDuration(size_t id, AudioContext* context){
	uint64_t sampleRate{context->soundClips->at(id)->device.sampleRate};
	uint64_t duration{ma_decoder_get_length_in_pcm_frames(&context->soundClips->at(id)->decoder)};
	return duration/(sampleRate/1000);
}

extern "C" bool isPlaying(size_t id, AudioContext* context){
  	return ma_device_is_started(&context->soundClips->at(id)->device);
}