From 5d56921aeb3a6cfce9ba07b68b36658d95e86571 Mon Sep 17 00:00:00 2001 From: snt Date: Mon, 20 May 2024 19:00:05 +0200 Subject: [PATCH 1/3] =?UTF-8?q?refactorizado=20todo=20a=20una=20struct.=20?= =?UTF-8?q?Maximo=20de=20dispositivos=20MAX=5FAUDIODEVICES,=20sin=20testea?= =?UTF-8?q?r=20mas=20de=20dos.=20Los=20devices=20auxiliares=20leen=20de=20?= =?UTF-8?q?data=20source=20rb=20en=20vez=20de=20en=20el=20callback.=20la?= =?UTF-8?q?=20idea=20del=20nodegraph=20funcionando=20en=20una=20engine=20d?= =?UTF-8?q?ummy=20no=20ha=20funcionado,=20pero=20puede=20que=20fuera=20por?= =?UTF-8?q?=20la=20refactorizaci=C3=B3n=20y=20la=20introducci=C3=B3n=20de?= =?UTF-8?q?=20las=20data=20sources=20rb.=20Ahora=20que=20est=C3=A1=20todo?= =?UTF-8?q?=20m=C3=A1s=20ordenado=20se=20puede=20volver=20a=20intentar.=20?= =?UTF-8?q?Pero=20tampoco=20merece=20mucho=20la=20pena,=20la=20principal?= =?UTF-8?q?=20diferencia=20era=20el=20master=20bus,=20pero=20se=20puede=20?= =?UTF-8?q?atacar=20la=20salida=20de=20auxNode[0]=20a=20una=20capa=20de=20?= =?UTF-8?q?master=20en=20vez=20de=20al=20endpoint=20directamente.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libremediaserver-audio.cpp | 7 +- src/ma_writer_node.c | 1 - src/miniaudioengine.cpp | 415 ++++++++++++++++----------------- src/miniaudioengine.h | 61 +++-- 4 files changed, 234 insertions(+), 250 deletions(-) diff --git a/src/libremediaserver-audio.cpp b/src/libremediaserver-audio.cpp index 76f711d..72398ee 100644 --- a/src/libremediaserver-audio.cpp +++ b/src/libremediaserver-audio.cpp @@ -40,15 +40,10 @@ libreMediaServerAudio::libreMediaServerAudio() m_updateUi[i][3] = -1; #endif } - if (!m_mae.startEngine(m_layersQty)) { + if (!m_mae.startEngine(m_layersQty, m_settings->getAudioDeviceId(), m_settings->getAudioDeviceQty())) { cout << "Can not start Audio Engine!" << endl; exit(-1); } - uint *audioDevList = m_settings->getAudioDeviceId(); - if (!m_mae.startDevice(audioDevList, m_settings->getAudioDeviceQty())) { - cout << "Can not start Audio Device!" << audioDevList << endl; - exit(-1); - } m_ola = new olaThread(this, m_layersQty); Q_CHECK_PTR(m_ola); m_ola->blockSignals(true); diff --git a/src/ma_writer_node.c b/src/ma_writer_node.c index f58881d..82e057c 100644 --- a/src/ma_writer_node.c +++ b/src/ma_writer_node.c @@ -28,7 +28,6 @@ static void ma_writer_node_process_pcm_frames(ma_node* pNode, const float** ppFr ma_pcm_rb_commit_write(pWriteNode->pBuffer, *pFrameCountIn); } } - //*pFrameCountOut = 0; ma_copy_pcm_frames(ppFramesOut[0], ppFramesIn[0], *pFrameCountOut, ma_format_f32, pWriteNode->channels); } diff --git a/src/miniaudioengine.cpp b/src/miniaudioengine.cpp index 33c7840..9b2f64a 100644 --- a/src/miniaudioengine.cpp +++ b/src/miniaudioengine.cpp @@ -4,10 +4,6 @@ #define BIAS 0.99f #define FILTER_ORDER 3 -static ma_pcm_rb aux1Buffer; -static ma_data_source_node g_dataSupplyNode; -static ma_data_source_rb g_dataSourceRB; - MiniAudioEngine::MiniAudioEngine() {} void MiniAudioEngine::audioDataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) @@ -21,83 +17,78 @@ void MiniAudioEngine::audioDataCallback(ma_device* pDevice, void* pOutput, const (void)pInput; } -void MiniAudioEngine::audioDataCallback1(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) -{ - (void)pDevice; - ma_result result; - - ma_uint32 pcmFramesAvailableInRB = 0; - ma_uint32 pcmFramesProcessed = 0; - while (pcmFramesProcessed < frameCount) { - pcmFramesAvailableInRB = ma_pcm_rb_available_read(&aux1Buffer); - if (pcmFramesAvailableInRB == 0) { - break; - } - ma_uint32 framesToRead = frameCount - pcmFramesProcessed; - if (framesToRead > pcmFramesAvailableInRB) { - framesToRead = pcmFramesAvailableInRB; - } - void* pReadBuffer = NULL; - ma_pcm_rb_acquire_read(&aux1Buffer, &framesToRead, &pReadBuffer); - if (pReadBuffer != NULL) { - ma_copy_pcm_frames(pOutput, pReadBuffer, framesToRead, FORMAT, CHANNELS); - ma_pcm_rb_commit_read(&aux1Buffer, framesToRead); - pcmFramesProcessed += framesToRead; - }/* else { break; }*/ - } - (void)pInput; -} - void MiniAudioEngine::stopEngine() { - for (uint i = 0; i < m_layersQty; i++) { - ma_sound_uninit(&m_currentSound[i]); + for (uint i = 0; i < m_mae.layersQty; i++) { + if (m_mae.mediaLoaded[i]) + ma_sound_uninit(&m_mae.sounds[i]); } - for (uint i = 0; i < m_devicesSelected; i++) { - for (uint j = 0; j < m_layersQty; j++) { - ma_node_uninit(&m_filterBank[i][j].input, NULL); - ma_hpf_node_uninit(&m_filterBank[i][j].hpf, NULL); - ma_loshelf_node_uninit(&m_filterBank[i][j].loshelf, NULL); - ma_peak_node_uninit(&m_filterBank[i][j].mLow, NULL); - ma_peak_node_uninit(&m_filterBank[i][j].mHigh, NULL); - ma_hishelf_node_uninit(&m_filterBank[i][j].hishelf, NULL); - ma_splitter_node_uninit(&m_filterBank[i][j].output, NULL); + for (uint i = 0; i < m_mae.layersQty; i++) { + ma_node_uninit(&m_mae.filters[i].input, NULL); + ma_hpf_node_uninit(&m_mae.filters[i].hpf, NULL); + ma_loshelf_node_uninit(&m_mae.filters[i].loshelf, NULL); + ma_peak_node_uninit(&m_mae.filters[i].mLow, NULL); + ma_peak_node_uninit(&m_mae.filters[i].mHigh, NULL); + ma_hishelf_node_uninit(&m_mae.filters[i].hishelf, NULL); + ma_splitter_node_uninit(&m_mae.filters[i].output, NULL); + } + for (uint i = 0; i < m_mae.audioDevicesQty; i++) { + if (i > 0) { + ma_writer_node_uninit(&m_mae.sendAuxNode[i], NULL); + ma_pcm_rb_uninit(&m_mae.auxBuffers[i]); } - //ma_writer_node_uninit(&m_sendToAux[0], NULL); - //ma_pcm_rb_uninit(&aux1Buffer); - ma_engine_uninit(&m_engine[i]); - ma_device_uninit(&m_device[i]); + ma_engine_uninit(&m_mae.engines[i]); + ma_device_uninit(&m_mae.devices[i]); } - ma_context_uninit(&m_context); - ma_resource_manager_uninit(&m_resourceManager); + ma_context_uninit(&m_mae.context); + ma_resource_manager_uninit(&m_mae.resourceManager); } -bool MiniAudioEngine::startEngine(uint layers) +bool MiniAudioEngine::startEngine(uint layers, uint* audioDevicesId, uint audioDevicesQty) { ma_result result; - m_layersQty = layers; - for (uint i =0; i < m_layersQty; i++) { - m_mediaLoaded[i] = false; - m_currentLayerValues[i].status = Status::Iddle; - m_currentLayerValues[i].pan = 128; - m_currentLayerValues[i].pitch = 128; - m_currentLayerValues[i].vol = 0; - m_currentLayerValues[i].cursor = 0; + m_mae.layersQty = layers; + m_mae.audioDevicesId = audioDevicesId; + m_mae.audioDevicesQty = audioDevicesQty; + for (uint i =0; i < m_mae.layersQty; i++) { + m_mae.mediaLoaded[i] = false; + m_mae.currentStatus[i].status = Status::Iddle; + m_mae.currentStatus[i].pan = 128; + m_mae.currentStatus[i].pitch = 128; + m_mae.currentStatus[i].vol = 0; + m_mae.currentStatus[i].cursor = 0; } result = this->startContext(); if (result != MA_SUCCESS) return false; result = this->getAllAudioDevices(); if (result != MA_SUCCESS) return false; + result = this->startDevices(); + if (result != MA_SUCCESS) { + cout << "Error " << result << ": Failed start audio devices." << endl; + return false; + } + result = this->setNodeGraph(); + if (result != MA_SUCCESS) { + cout << "Error " << result << ": Failed to set node graph." << endl; + return false; + } + for (uint i = 0; i < m_mae.audioDevicesQty; i++) { + result = ma_engine_start(&m_mae.engines[i]); + if (result != MA_SUCCESS) { + cout << "Error " << result << ": Failed to start audio device" << m_mae.audioDevicesId[i] << endl; + return false; + } + } return true; } -ma_result MiniAudioEngine::createFilterBank(int id, uint layer) +ma_result MiniAudioEngine::createFilterBank(uint layer) { ma_result result; - ma_node_graph *ng = ma_engine_get_node_graph(&m_engine[id]); - ma_node *endpoint = ma_engine_get_endpoint(&m_engine[id]); - filterBank *fb = &m_filterBank[id][layer]; + ma_node_graph *ng = ma_engine_get_node_graph(&m_mae.engines[0]); + ma_node *endpoint = ma_engine_get_endpoint(&m_mae.engines[0]); + filterBank *fb = &m_mae.filters[layer]; ma_splitter_node_config splitterConfig = ma_splitter_node_config_init(CHANNELS); result = ma_splitter_node_init(ng, &splitterConfig, NULL, &fb->input); @@ -140,13 +131,12 @@ ma_result MiniAudioEngine::createFilterBank(int id, uint layer) cout << "ERROR " << result << ": Failed to init hi shelf filter node." << endl; return result; } - + splitterConfig.outputBusCount = m_mae.audioDevicesQty; result = ma_splitter_node_init(ng, &splitterConfig, NULL, &fb->output); if (result != MA_SUCCESS) { cout << "ERROR " << result << ": Failed to init output node." << endl; return result; } - result = ma_node_attach_output_bus(&fb->input, 0, &fb->hpf, 0); if (result != MA_SUCCESS) { cout << "ERROR " << result << ": Failed to attach input node." << endl; @@ -183,137 +173,143 @@ ma_result MiniAudioEngine::createFilterBank(int id, uint layer) cout << "ERROR " << result << ": Failed to attach high shelf filter node." << endl; return result; } -if (id == 0) { - result = ma_node_attach_output_bus(&fb->output, 0, &m_sendToAux[id], 0); + if (m_mae.audioDevicesQty == 1) { + result = ma_node_attach_output_bus(&fb->output, 0, endpoint, 0); if (result != MA_SUCCESS) { - cout << "ERROR " << result << ": Failed to attach output node to engine." << endl; + cout << "ERROR " << result << ": Failed to attach output to endpoint." << endl; return result; } - result = ma_node_attach_output_bus(&fb->output, 1, &m_sendToAux[id], 1); + } else { + result = ma_node_attach_output_bus(&fb->output, 0, &m_mae.sendAuxNode[1], 0); if (result != MA_SUCCESS) { cout << "ERROR " << result << ": Failed to attach output node to aux send 1." << endl; return result; } + result = ma_node_attach_output_bus(&fb->output, 1, &m_mae.sendAuxNode[1], 1); + if (result != MA_SUCCESS) { + cout << "ERROR " << result << ": Failed to attach output node to aux send 1." << endl; + return result; + } + for (uint i = 2; i < m_mae.audioDevicesQty; i++) { + result = ma_node_attach_output_bus(&fb->output, i, &m_mae.sendAuxNode[i], 1); + if (result != MA_SUCCESS) { + cout << "ERROR " << result << ": Failed to attach output node to aux send 1." << endl; + return result; + } + } } return result; } -ma_result MiniAudioEngine::setNodeGraph(int id) { +ma_result MiniAudioEngine::setNodeGraph() { ma_result result = MA_SUCCESS; - uint i = 0; - if (id == 0) { - ma_node_graph *ng = ma_engine_get_node_graph(&m_engine[id]); - size_t sizeInFrames = SAMPLE_RATE; // ma_get_bytes_per_frame(FORMAT, CHANNELS); - result = ma_pcm_rb_init(FORMAT, CHANNELS, sizeInFrames, NULL, NULL, &aux1Buffer); - if (result != MA_SUCCESS) { - printf("Failed to initialize ring buffer.\n"); - return result; - } - ma_silence_pcm_frames(aux1Buffer.rb.pBuffer, sizeInFrames, FORMAT, CHANNELS); - ma_writer_node_config writerConfig = ma_writer_node_config_init(CHANNELS, SAMPLE_RATE * 5, &aux1Buffer); - result = ma_writer_node_init(ng, &writerConfig, NULL, &m_sendToAux[id]); - if (result != MA_SUCCESS) { - cout << "ERROR " << result << ": Failed to init writer node." << endl; - return result; - } - result = ma_node_attach_output_bus(&m_sendToAux[id], 0, ma_engine_get_endpoint(&m_engine[id]), 0); // Pull API - if (result != MA_SUCCESS) { - cout << "ERROR " << result << ": Failed to attach writer node." << endl; - return result; - } + ma_node_graph *ng = ma_engine_get_node_graph(&m_mae.engines[0]); + for (uint i = 1; i < m_mae.audioDevicesQty; i++) { + size_t sizeInFrames = SAMPLE_RATE; + result = ma_pcm_rb_init(FORMAT, CHANNELS, sizeInFrames, NULL, NULL, &m_mae.auxBuffers[i]); + if (result != MA_SUCCESS) { + printf("Failed to initialize ring buffer.\n"); + return result; + } + ma_silence_pcm_frames(m_mae.auxBuffers[i].rb.pBuffer, sizeInFrames, FORMAT, CHANNELS); + ma_writer_node_config writerConfig = ma_writer_node_config_init(CHANNELS, SAMPLE_RATE * 5, &m_mae.auxBuffers[i]); + result = ma_writer_node_init(ng, &writerConfig, NULL, &m_mae.sendAuxNode[i]); + if (result != MA_SUCCESS) { + cout << "ERROR " << result << ": Failed to init writer node." << endl; + return result; + } + // esto va a dar problemas al sumar en el envío 0 una vez por cad envío extra. + // writer_node puede ser silencioso + // así ya estamos en el caso de disparar varios bang por cada envío en el mismo nodegraph + // es mejor que writer node tenga varias entradas, una por cada envío + // que se dispara con un único engine y proporciona un único stream de audio de vuelta a ese engine + // en vez de un puntero hay que pasarle un array de rb + result = ma_node_attach_output_bus(&m_mae.sendAuxNode[i], 0, ma_engine_get_endpoint(&m_mae.engines[0]), 0); + if (result != MA_SUCCESS) { + cout << "ERROR " << result << ": Failed to attach writer node." << endl; + return result; + } + result = ma_data_source_rb_init(&m_mae.dataSourceRB[i], &m_mae.auxBuffers[i]); + if (result != MA_SUCCESS) { + cout << "Error " << result << ": Failed to init data source ring buffer" << endl; + return result; + } + ma_data_source_node_config dataSupplyNodeConfig = ma_data_source_node_config_init(&m_mae.dataSourceRB[i]); + result = ma_data_source_node_init(ma_engine_get_node_graph(&m_mae.engines[i]), &dataSupplyNodeConfig, NULL, &m_mae.dataSupplyNode[i]); + if (result != MA_SUCCESS) { + cout << "Error " << result << ": Failed to init data source node" << endl; + return result; + } + result = ma_node_attach_output_bus(&m_mae.dataSupplyNode[i], 0, ma_engine_get_endpoint(&m_mae.engines[i]), 0); + if (result != MA_SUCCESS) { + cout << "Error " << result << ": Failed to attach data source rb node" << endl; + return result; + } } - while (result == MA_SUCCESS && i < m_layersQty) { - result = this->createFilterBank(id, i); - i++; + for (uint i = 0; i < m_mae.layersQty; i++) { + result = this->createFilterBank(i); + if (result != MA_SUCCESS) { + cout << "ERROR " << result << ": Failed creating filter bank." << endl; + } } return (result); } -bool MiniAudioEngine::startDevice(uint *systemId, uint nb) +ma_result MiniAudioEngine::startDevices() { ma_result result = MA_SUCCESS; ma_device_config deviceConfig; ma_engine_config engineConfig; - m_devicesSelected = nb; - for (uint internalId = 0; internalId < nb; internalId++) { - deviceConfig = ma_device_config_init(ma_device_type_duplex); - deviceConfig.capture.pDeviceID = &m_pPlaybackDeviceInfos[systemId[internalId]].id; - deviceConfig.capture.format = m_resourceManager.config.decodedFormat; - deviceConfig.capture.channels = CHANNELS; - deviceConfig.capture.shareMode = ma_share_mode_shared; - deviceConfig.playback.pDeviceID = &m_pPlaybackDeviceInfos[systemId[internalId]].id; - deviceConfig.playback.format = m_resourceManager.config.decodedFormat; - deviceConfig.playback.channels = CHANNELS; - deviceConfig.sampleRate = m_resourceManager.config.decodedSampleRate; - if (internalId == 0) - deviceConfig.dataCallback = audioDataCallback; - else if (internalId == 1) - deviceConfig.dataCallback = audioDataCallback1; - deviceConfig.pUserData = &m_engine[internalId]; - result = ma_device_init(&m_context, &deviceConfig, &m_device[internalId]); + deviceConfig = ma_device_config_init(ma_device_type_duplex); + deviceConfig.capture.format = m_mae.resourceManager.config.decodedFormat; + deviceConfig.capture.channels = CHANNELS; + deviceConfig.playback.channels = CHANNELS; + deviceConfig.capture.shareMode = ma_share_mode_shared; + deviceConfig.playback.format = m_mae.resourceManager.config.decodedFormat; + deviceConfig.sampleRate = m_mae.resourceManager.config.decodedSampleRate; + deviceConfig.dataCallback = audioDataCallback; + engineConfig = ma_engine_config_init(); + engineConfig.pResourceManager = &m_mae.resourceManager; + engineConfig.gainSmoothTimeInMilliseconds = SAMPLE_RATE / 25; + engineConfig.noAutoStart = MA_TRUE; + + for (uint internalId = 0; internalId < m_mae.audioDevicesQty; internalId++) { + deviceConfig.capture.pDeviceID = &m_mae.pPlaybackDeviceInfos[m_mae.audioDevicesId[internalId]].id; + deviceConfig.playback.pDeviceID = &m_mae.pPlaybackDeviceInfos[m_mae.audioDevicesId[internalId]].id; + deviceConfig.pUserData = &m_mae.engines[internalId]; + result = ma_device_init(&m_mae.context, &deviceConfig, &m_mae.devices[internalId]); if (result != MA_SUCCESS) { - cout << "Error " << result << ": Failed to initialize audio device " << m_pPlaybackDeviceInfos[*systemId].name << endl; - return false; + cout << "Error " << result << ": Failed to initialize audio device " << m_mae.pPlaybackDeviceInfos[m_mae.audioDevicesId[internalId]].name << endl; + return result; } - engineConfig = ma_engine_config_init(); - engineConfig.pDevice = &m_device[internalId]; - engineConfig.pResourceManager = &m_resourceManager; - engineConfig.gainSmoothTimeInMilliseconds = SAMPLE_RATE / 100; - engineConfig.noAutoStart = MA_TRUE; - result = ma_engine_init(&engineConfig, &m_engine[internalId]); + engineConfig.pDevice = &m_mae.devices[internalId]; + result = ma_engine_init(&engineConfig, &m_mae.engines[internalId]); if (result != MA_SUCCESS) { cout << "Error " << result << ": Failed to initialize audio engine" << endl; - return false; + return result; } - result = this->setNodeGraph(internalId); - if (result != MA_SUCCESS) { - cout << "Error " << result << ": Failed to set node graph " << systemId[internalId] << endl; - return false; - } - result = ma_engine_start(&m_engine[internalId]); - if (result != MA_SUCCESS) { - cout << "Error " << result << ": Failed to start audio engine" << systemId[internalId] << endl; - return false; - } - cout << "Initialized Audio Device. internalId: " << internalId << " systemId: " << systemId[internalId] << " " << m_pPlaybackDeviceInfos[systemId[internalId]].name << endl; + cout << "Initialized Audio Device. internalId: " << internalId << " systemId: " << m_mae.audioDevicesId[internalId] << " " << m_mae.pPlaybackDeviceInfos[m_mae.audioDevicesId[internalId]].name << endl; } - //result = ma_data_source_rb_init(&g_dataSourceRB, &aux1Buffer); - if (result != MA_SUCCESS) { - cout << "Error " << result << ": Failed to init data source ring buffer" << endl; - return false; - } - ma_data_source_node_config dataSupplyNodeConfig = ma_data_source_node_config_init(&g_dataSourceRB); - //result = ma_data_source_node_init(ma_engine_get_node_graph(&m_engine[1]), &dataSupplyNodeConfig, NULL, &g_dataSupplyNode); - if (result != MA_SUCCESS) { - cout << "Error " << result << ": Failed to init data source node" << endl; - return false; - } - //result = ma_node_attach_output_bus(&g_dataSupplyNode, 0, ma_engine_get_endpoint(&m_engine[1]), 0); - if (result != MA_SUCCESS) { - cout << "Error " << result << ": Failed to attach data source rb node" << endl; - return false; - } - cout << "data source node state " << ma_node_get_state(&g_dataSupplyNode.base) << endl; - return true; + return result; } ma_result MiniAudioEngine::startContext() { ma_result result; - m_resourceManagerConfig = ma_resource_manager_config_init(); - m_resourceManagerConfig.decodedFormat = FORMAT; - m_resourceManagerConfig.decodedChannels = CHANNELS; - m_resourceManagerConfig.decodedSampleRate = SAMPLE_RATE; - m_resourceManagerConfig.jobThreadCount = 4; - result = ma_resource_manager_init(&m_resourceManagerConfig, &m_resourceManager); + ma_resource_manager_config resourceManagerConfig = ma_resource_manager_config_init(); + resourceManagerConfig.decodedFormat = FORMAT; + resourceManagerConfig.decodedChannels = CHANNELS; + resourceManagerConfig.decodedSampleRate = SAMPLE_RATE; + resourceManagerConfig.jobThreadCount = MAX_LAYERS; + result = ma_resource_manager_init(&resourceManagerConfig, &m_mae.resourceManager); if (result != MA_SUCCESS) { cout << "Error " << result << ": Failed to initialize audio resource manager." << endl; return result; } - result = ma_context_init(NULL, 0, NULL, &m_context); + result = ma_context_init(NULL, 0, NULL, &m_mae.context); if (result != MA_SUCCESS) { cout << "Error " << result << ": Failed to initialize audio context." << endl; } @@ -325,15 +321,15 @@ ma_result MiniAudioEngine::getAllAudioDevices() { ma_result result; - result = ma_context_get_devices(&m_context, &m_pPlaybackDeviceInfos, &m_playbackDeviceCount, NULL, NULL); + result = ma_context_get_devices(&m_mae.context, &m_mae.pPlaybackDeviceInfos, &m_mae.playbackDeviceCount, NULL, NULL); if (result != MA_SUCCESS) { cout << "Error " << result << ": Failed to enumerate playback devices." << endl; - ma_context_uninit(&m_context); + ma_context_uninit(&m_mae.context); return result; } cout << "Audio devices available:" << endl; - for (ma_uint32 iAvailableDevice = 0; iAvailableDevice < m_playbackDeviceCount; iAvailableDevice += 1) { - cout << iAvailableDevice << " : " << m_pPlaybackDeviceInfos[iAvailableDevice].name << endl; + for (ma_uint32 iAvailableDevice = 0; iAvailableDevice < m_mae.playbackDeviceCount; iAvailableDevice += 1) { + cout << iAvailableDevice << " : " << m_mae.pPlaybackDeviceInfos[iAvailableDevice].name << endl; } return result; } @@ -342,28 +338,26 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file, uint audioDevice) { ma_result result; - // - iniciar un sonido por cada capa, copiar la capa en otro dispositivo - // - writer node y source con el buffer escrito en el otro device - if (m_mediaLoaded[layer] == true) + if (m_mae.mediaLoaded[layer] == true) { - ma_sound_uninit(&m_currentSound[layer]); - m_mediaLoaded[layer] = false; + ma_sound_uninit(&m_mae.sounds[layer]); + m_mae.mediaLoaded[layer] = false; } - result = ma_sound_init_from_file(&m_engine[audioDevice], file, \ + result = ma_sound_init_from_file(&m_mae.engines[0], file, \ MA_SOUND_FLAG_NO_SPATIALIZATION \ - , NULL, NULL, &m_currentSound[layer]); + , NULL, NULL, &m_mae.sounds[layer]); if (result != MA_SUCCESS) { cout << "Error " << result << ": Failed to load file " << file << endl; return result; } - result = ma_node_attach_output_bus(&m_currentSound[layer], 0, &m_filterBank[audioDevice][layer].input, 0); + result = ma_node_attach_output_bus(&m_mae.sounds[layer], 0, &m_mae.filters[layer].input, 0); if (result != MA_SUCCESS) { cout << "Error " << result << ": Failed to attach sound output bus " << audioDevice << endl; - //return result; + return result; } - m_mediaLoaded[layer] = true; + m_mae.mediaLoaded[layer] = true; this->refreshValues(layer); - m_currentLayerValues[layer].media = file; + m_mae.currentStatus[layer].media = file; return result; } @@ -372,9 +366,9 @@ float MiniAudioEngine::getDuration(int layer) ma_result result; float ret; - if (m_mediaLoaded[layer] == false) + if (m_mae.mediaLoaded[layer] == false) return MA_DOES_NOT_EXIST; - result = ma_sound_get_length_in_seconds(&m_currentSound[layer], &ret); + result = ma_sound_get_length_in_seconds(&m_mae.sounds[layer], &ret); if (result != MA_SUCCESS) { return result; } @@ -386,9 +380,9 @@ float MiniAudioEngine::getCursor(int layer) ma_result result; float ret = 0; - if (m_mediaLoaded[layer] == false) + if (m_mae.mediaLoaded[layer] == false) return MA_DOES_NOT_EXIST; - result = ma_sound_get_cursor_in_seconds(&m_currentSound[layer], &ret); + result = ma_sound_get_cursor_in_seconds(&m_mae.sounds[layer], &ret); if (result != MA_SUCCESS) { cout << "Error" << result << ": Can not get cursor " << layer << endl; @@ -403,16 +397,16 @@ ma_result MiniAudioEngine::printFormatInfo(int layer) ma_uint32 channels; ma_uint32 sampleRate; - if (m_mediaLoaded[layer] == false) + if (m_mae.mediaLoaded[layer] == false) return MA_DOES_NOT_EXIST; - ma_result result = ma_sound_get_data_format(&m_currentSound[layer], \ + ma_result result = ma_sound_get_data_format(&m_mae.sounds[layer], \ &format, &channels, &sampleRate, NULL, 0); if (result != MA_SUCCESS) { cout << "Error " << result << ": Failed to get data format " << layer; cout << endl; } else { cout << "Layer:" << layer << " "; - cout << m_currentLayerValues[layer].media.toLatin1().data(); + cout << m_mae.currentStatus[layer].media.toLatin1().data(); cout << " samples/sec:" << sampleRate << " format:" << format; cout << " channels:" << channels << endl; } @@ -422,50 +416,50 @@ ma_result MiniAudioEngine::printFormatInfo(int layer) // Expects between 0 and 1 vol value void MiniAudioEngine::volChanged(int layer, float vol) { - if (m_mediaLoaded[layer] == false) + if (m_mae.mediaLoaded[layer] == false) return; if (vol >= 1) vol = 0.99f; - ma_sound_group_set_fade_in_milliseconds(&m_currentSound[layer], -1, pow(vol, 3), FADE_TIME); - m_currentLayerValues[layer].vol = vol; + ma_sound_group_set_fade_in_milliseconds(&m_mae.sounds[layer], -1, pow(vol, 3), FADE_TIME); + m_mae.currentStatus[layer].vol = vol; } void MiniAudioEngine::panChanged(int layer, float value) { float result; - if (m_mediaLoaded[layer] == false) + if (m_mae.mediaLoaded[layer] == false) return; result = (value / 128.0) - 1.0; - ma_sound_group_set_pan(&m_currentSound[layer], result); - m_currentLayerValues[layer].pan = value; + ma_sound_group_set_pan(&m_mae.sounds[layer], result); + m_mae.currentStatus[layer].pan = value; } void MiniAudioEngine::pitchChanged(int layer, float value) { float pitch; - if (m_mediaLoaded[layer] == false) + if (m_mae.mediaLoaded[layer] == false) return; pitch = value / 128.0; - ma_sound_group_set_pitch(&m_currentSound[layer], pitch); - m_currentLayerValues[layer].pitch = value; + ma_sound_group_set_pitch(&m_mae.sounds[layer], pitch); + m_mae.currentStatus[layer].pitch = value; } ma_result MiniAudioEngine::playbackChanged(int layer, Status status) { ma_result result = MA_SUCCESS; - if (m_mediaLoaded[layer] == false) + if (m_mae.mediaLoaded[layer] == false) return MA_DOES_NOT_EXIST; bool loop = false; switch (status) { case Status::Paused: - result = ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME); + result = ma_sound_stop_with_fade_in_milliseconds(&m_mae.sounds[layer], FADE_TIME); break; case Status::Stopped: - ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME); - result = this->seekToCursor(layer, m_currentLayerValues[layer].cursor); + ma_sound_stop_with_fade_in_milliseconds(&m_mae.sounds[layer], FADE_TIME); + result = this->seekToCursor(layer, m_mae.currentStatus[layer].cursor); break; case Status::PlayingLoop: loop = true; @@ -473,18 +467,18 @@ ma_result MiniAudioEngine::playbackChanged(int layer, Status status) case Status::PlayingFolder: case Status::PlayingFolderLoop: case Status::PlayingFolderRandom: - ma_sound_set_stop_time_in_milliseconds(&m_currentSound[layer], ~(ma_uint64)0); - ma_sound_set_looping(&m_currentSound[layer], loop); - result = ma_sound_start(&m_currentSound[layer]); - if (m_currentLayerValues[layer].cursor != 0) { + ma_sound_set_stop_time_in_milliseconds(&m_mae.sounds[layer], ~(ma_uint64)0); + ma_sound_set_looping(&m_mae.sounds[layer], loop); + result = ma_sound_start(&m_mae.sounds[layer]); + if (m_mae.currentStatus[layer].cursor != 0) { usleep(1000 * 50); // Avoid small glitch at start, how to flush the cached buffers in audio pipe line? } - this->volChanged(layer, m_currentLayerValues[layer].vol); + this->volChanged(layer, m_mae.currentStatus[layer].vol); default: break; } if (result == MA_SUCCESS) - m_currentLayerValues[layer].status = status; + m_mae.currentStatus[layer].status = status; return result; } @@ -493,13 +487,13 @@ ma_result MiniAudioEngine::seekToCursor(int layer, int cursor) ma_result result = MA_SUCCESS; ma_uint64 end, start; - if (m_mediaLoaded[layer] == false) + if (m_mae.mediaLoaded[layer] == false) return MA_DOES_NOT_EXIST; - result = ma_sound_get_length_in_pcm_frames(&m_currentSound[layer], &end); + result = ma_sound_get_length_in_pcm_frames(&m_mae.sounds[layer], &end); if (result != MA_SUCCESS) { return result; } start = (cursor * end) / 65025; - result = ma_sound_seek_to_pcm_frame(&m_currentSound[layer], start); - //result = ma_data_source_set_loop_point_in_pcm_frames(&m_currentSound[layer], start, end); // this do nothing here, it must be done after set_looping or start? + result = ma_sound_seek_to_pcm_frame(&m_mae.sounds[layer], start); + //result = ma_data_source_set_loop_point_in_pcm_frames(&m_mae.sounds[layer], start, end); // this do nothing here, it must be done after set_looping or start? return (result); } @@ -507,30 +501,30 @@ ma_result MiniAudioEngine::setCursor(int layer, int cursor) { ma_result result = MA_SUCCESS; - m_currentLayerValues[layer].cursor = cursor; + m_mae.currentStatus[layer].cursor = cursor; result = this->seekToCursor(layer, cursor); return (result); } Status MiniAudioEngine::getStatus(int layer) { - return m_currentLayerValues[layer].status; + return m_mae.currentStatus[layer].status; } void MiniAudioEngine::refreshValues(int layer) { - this->seekToCursor(layer, m_currentLayerValues[layer].cursor); - this->panChanged(layer, m_currentLayerValues[layer].pan); - this->volChanged(layer, m_currentLayerValues[layer].vol); - this->pitchChanged(layer, m_currentLayerValues[layer].pitch); - this->playbackChanged(layer, m_currentLayerValues[layer].status); + this->seekToCursor(layer, m_mae.currentStatus[layer].cursor); + this->panChanged(layer, m_mae.currentStatus[layer].pan); + this->volChanged(layer, m_mae.currentStatus[layer].vol); + this->pitchChanged(layer, m_mae.currentStatus[layer].pitch); + this->playbackChanged(layer, m_mae.currentStatus[layer].status); } ma_result MiniAudioEngine::filterParamChanged(int layer, int audioDevice, int channel, int value) { + (void)audioDevice; ma_result result = MA_SUCCESS; - - filterBank *fb = &m_filterBank[audioDevice][layer]; + filterBank *fb = &m_mae.filters[layer]; if (channel == HP_FREQ) { fb->hpfConfig.hpf.cutoffFrequency = double((value * 1.31) + 16.0f); // 16 - 350 @@ -641,7 +635,8 @@ ma_result MiniAudioEngine::filterParamChanged(int layer, int audioDevice, int ch bool MiniAudioEngine::setBypass(int audioDevice, int layer, bool bypass) { - filterBank *fb = &m_filterBank[audioDevice][layer]; + (void)audioDevice; + filterBank *fb = &m_mae.filters[layer]; if (bypass) { ma_node_set_output_bus_volume(&fb->input, 1, 1.0f); diff --git a/src/miniaudioengine.h b/src/miniaudioengine.h index 69147d3..308706b 100644 --- a/src/miniaudioengine.h +++ b/src/miniaudioengine.h @@ -15,7 +15,6 @@ using namespace std; #include "defines.h" - typedef struct { ma_splitter_node input; @@ -30,32 +29,40 @@ typedef struct ma_hishelf_node hishelf; ma_hishelf_node_config hishelfConfig; ma_splitter_node output; - ma_writer_node send1; - ma_data_source_node return1; - ma_audio_buffer_ref supplyReturn1; } filterBank; typedef struct { - ma_engine m_engine[MAX_AUDIODEVICES]; - filterBank m_filterBank[MAX_AUDIODEVICES][MAX_LAYERS]; - ma_writer_node m_sendAux1[MAX_LAYERS]; - ma_pcm_rb *aux1Buffer; -} audioObjects; + ma_engine engines[MAX_AUDIODEVICES]; + ma_device devices[MAX_AUDIODEVICES]; + filterBank filters[MAX_LAYERS]; + ma_writer_node sendAuxNode[MAX_AUDIODEVICES]; + ma_pcm_rb auxBuffers[MAX_AUDIODEVICES]; + ma_node_graph ng; + layerData currentStatus[MAX_LAYERS]; + ma_sound sounds[MAX_LAYERS]; + ma_resource_manager resourceManager; + ma_context context; + ma_device_info* pPlaybackDeviceInfos; + ma_uint32 playbackDeviceCount; + ma_uint32 devicesSelected; + ma_bool8 mediaLoaded[MAX_LAYERS]; + uint layersQty; + uint *audioDevicesId; + uint audioDevicesQty; + ma_data_source_node dataSupplyNode[MAX_AUDIODEVICES]; + ma_data_source_rb dataSourceRB[MAX_AUDIODEVICES]; +} MAE; class MiniAudioEngine { friend class libreMediaServerAudio; - static ma_pcm_rb *rb; public: MiniAudioEngine(); void stopEngine(); - bool startEngine(uint layersQty); - bool startDevice(uint *id, uint nb); + bool startEngine(uint layersQty, uint* audioDevicesID, uint audioDevicesQty); static void audioDataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount); - static void audioDataCallback1(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount); - bool setBypass(int audioDevice, int layer, bool bypass); protected: ma_result loadMedia(int layer, char *media, uint audioDevice); @@ -69,33 +76,21 @@ protected: float getCursor(int layer); Status getStatus(int layer); inline float getVol(int layer) { - return ma_sound_get_volume(&m_currentSound[layer]); } - inline bool getAtEnd(int layer) { return m_currentSound[layer].atEnd; } + return ma_sound_get_volume(&m_mae.sounds[layer]); } + inline bool getAtEnd(int layer) { return m_mae.sounds[layer].atEnd; } ma_result filterParamChanged(int layer, int audioDevice, int channel, int value); + bool setBypass(int audioDevice, int layer, bool bypass); private: - ma_resource_manager_config m_resourceManagerConfig; - ma_resource_manager m_resourceManager; - ma_context m_context; - ma_device_info* m_pPlaybackDeviceInfos; - ma_uint32 m_playbackDeviceCount; - ma_uint32 m_devicesSelected; - ma_device m_device[MAX_AUDIODEVICES]; - ma_sound m_currentSound[MAX_LAYERS]; - ma_bool8 m_mediaLoaded[MAX_LAYERS]; - layerData m_currentLayerValues[MAX_LAYERS]; - filterBank m_filterBank[MAX_AUDIODEVICES][MAX_LAYERS]; - ma_engine m_engine[MAX_AUDIODEVICES]; - uint m_layersQty; - ma_writer_node m_sendToAux[MAX_LAYERS]; - audioObjects m_audioObjects; + MAE m_mae; + ma_result startDevices(); ma_result getAllAudioDevices(); ma_result startContext(); void refreshValues(int layer); ma_result seekToCursor(int layer, int cursor); - ma_result setNodeGraph(int id); - ma_result createFilterBank(int id, uint layer); + ma_result setNodeGraph(); + ma_result createFilterBank(uint layer); }; #endif // MINIAUDIOENGINE_H From f0f6e595fb0797e7eaa365b486a8ed64fbcc4674 Mon Sep 17 00:00:00 2001 From: snt Date: Mon, 20 May 2024 20:08:26 +0200 Subject: [PATCH 2/3] =?UTF-8?q?cambiada=20curva=20de=20volume=20de=20c?= =?UTF-8?q?=C3=BAbia=20a=20cuadr=C3=A1tica,=20en=20pruebas=20a=20ver=20si?= =?UTF-8?q?=20es=20suficiente.=20valuebox=20de=20volumen=20en=20decibelios?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/audiolayerwidget.cpp | 2 +- src/miniaudioengine.cpp | 2 +- src/slidergroup.cpp | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/audiolayerwidget.cpp b/src/audiolayerwidget.cpp index c3b1f86..3528f50 100644 --- a/src/audiolayerwidget.cpp +++ b/src/audiolayerwidget.cpp @@ -82,7 +82,7 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer): m_pan = new SliderGroup("Pan", 0 , 255, 0, NULL); volumeBox->addWidget(m_pan); connect(m_pan, SIGNAL(valueChanged(int)), this, SLOT(panChanged(int))); - m_volume = new SliderGroup("Vol", 0 , 100, 2, NULL); + m_volume = new SliderGroup("Vol", 0, 100, 2, NULL); volumeBox->addWidget(m_volume); connect(m_volume, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int))); volumeBox->setSpacing(0); diff --git a/src/miniaudioengine.cpp b/src/miniaudioengine.cpp index 9b2f64a..0599fcc 100644 --- a/src/miniaudioengine.cpp +++ b/src/miniaudioengine.cpp @@ -420,7 +420,7 @@ void MiniAudioEngine::volChanged(int layer, float vol) return; if (vol >= 1) vol = 0.99f; - ma_sound_group_set_fade_in_milliseconds(&m_mae.sounds[layer], -1, pow(vol, 3), FADE_TIME); + ma_sound_group_set_fade_in_milliseconds(&m_mae.sounds[layer], -1, pow(vol, 2), FADE_TIME); m_mae.currentStatus[layer].vol = vol; } diff --git a/src/slidergroup.cpp b/src/slidergroup.cpp index c8e267d..55bfcf7 100644 --- a/src/slidergroup.cpp +++ b/src/slidergroup.cpp @@ -1,5 +1,5 @@ #include "slidergroup.h" - +#include #include #include @@ -39,7 +39,10 @@ SliderGroup::SliderGroup(QString name, valueBox.setFocusPolicy(Qt::NoFocus); valueBox.setButtonSymbols(QAbstractSpinBox::NoButtons); valueBox.setMinimumWidth(50); - valueBox.setRange(min, max); + if (decimals) + valueBox.setRange(-100, 100); + else + valueBox.setRange(min, max); valueBox.setValue(0); valueBox.setDecimals(decimals); valueBox.setObjectName(name); @@ -51,7 +54,7 @@ SliderGroup::SliderGroup(QString name, layout->addWidget(&slider); layout->addWidget(&valueBox); this->setStyleSheet("border: 1px solid #5a4855;" - "width: 50px;" + "width: 60px;" "margin: 0px;" "background-color: #383034;" ); @@ -74,7 +77,10 @@ void SliderGroup::setValue(float value) valueBox.blockSignals(true); if (int(value) != slider.value()) slider.setValue(value); - valueBox.setValue(value); + if (valueBox.decimals()) + valueBox.setValue(value - 100.0f); + else + valueBox.setValue(value); slider.blockSignals(false); valueBox.blockSignals(false); } From 200dcf86d45e1d760368ebb9b772975da35cea19 Mon Sep 17 00:00:00 2001 From: snt Date: Tue, 21 May 2024 18:17:55 +0200 Subject: [PATCH 3/3] =?UTF-8?q?volumen=20y=20env=C3=ADos=20en=20logar?= =?UTF-8?q?=C3=ADtmico=20aut=C3=A9ntico,=20entre=20-85dB=20y=200.=20SLider?= =?UTF-8?q?s=20en=20UI=20para=20los=20env=C3=ADos=20(s=C3=B3lo=202,=20est?= =?UTF-8?q?=C3=A1ticos,=20hay=20que=20meter=20un=20bucle=20con=20el=20n?= =?UTF-8?q?=C3=BAmero=20de=20env=C3=ADos).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/roadmap.txt | 4 +++ src/audiolayerwidget.cpp | 58 +++++++++++++++++++++++----------- src/audiolayerwidget.h | 4 +++ src/audiowidget.cpp | 9 +++--- src/defines.h | 10 ++++-- src/dmxPersonality.h | 2 +- src/filterbankwidget.cpp | 3 +- src/libremediaserver-audio.cpp | 14 +++++--- src/miniaudioengine.cpp | 27 ++++++++++++---- src/miniaudioengine.h | 2 +- src/slidergroup.cpp | 22 +++++++++---- 11 files changed, 108 insertions(+), 47 deletions(-) diff --git a/docs/roadmap.txt b/docs/roadmap.txt index 154fd78..9e5ec0c 100644 --- a/docs/roadmap.txt +++ b/docs/roadmap.txt @@ -46,6 +46,10 @@ v 0.2.1 - Hardening: check return errors, try/catch exceptions, i'm too happy.... - Tests: errors on wrong conf file. - Ui/Ux: seek cursor playback +- ampliar writer para recibir un número n de entradas y escribirlas cada una en un buffer v0.2.0: - Vumeter or indicator about audio output in layer and master, add to sliderGroup. + --> en master se puede hacer con jack, solo en capas. + --> en las capas, hace falta otro nodo atacado en los buses de input que analice la entrada. +- mostrad información de envíos y dispositivos en ui diff --git a/src/audiolayerwidget.cpp b/src/audiolayerwidget.cpp index 3528f50..f37b67d 100644 --- a/src/audiolayerwidget.cpp +++ b/src/audiolayerwidget.cpp @@ -1,4 +1,5 @@ #include "audiolayerwidget.h" +#include "dmxPersonality.h" #include #include @@ -11,7 +12,6 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer): { QVBoxLayout *layout = new QVBoxLayout; - QVBoxLayout *playback = new QVBoxLayout; m_folderValue = new ClickableLabel; m_folderValue->setMaximumWidth(300); m_folderValue->setAlignment(Qt::AlignLeft); @@ -19,7 +19,7 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer): "color: white;" "background-color: black;" ); - playback->addWidget(m_folderValue); + layout->addWidget(m_folderValue); m_fileValue = new ClickableLabel; connect(m_fileValue, SIGNAL(clicked()), this, SLOT(openMediaDialog())); connect(m_folderValue, SIGNAL(clicked()), this, SLOT(openMediaDialog())); @@ -29,10 +29,7 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer): "color: white;" "background-color: black;" ); - playback->addWidget(m_fileValue); - playback->setSpacing(0); - playback->setContentsMargins(0, 0, 0, 0); - layout->addLayout(playback); + layout->addWidget(m_fileValue); m_suspendResumeButton = new QPushButton(this); m_suspendResumeButton->setText(statusToString(Status::Iddle)); @@ -74,17 +71,23 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer): m_filterBank = new FilterBankWidget(this); connect(m_filterBank, SIGNAL(setBypass(bool)), this, SLOT(setBypass(bool))); layout->addWidget(m_filterBank); - - QVBoxLayout *volumeBox = new QVBoxLayout; m_pitch = new SliderGroup("Pitch", 0 , 255, 0, NULL); - volumeBox->addWidget(m_pitch); + layout->addWidget(m_pitch); connect(m_pitch, SIGNAL(valueChanged(int)), this, SLOT(pitchChanged(int))); m_pan = new SliderGroup("Pan", 0 , 255, 0, NULL); - volumeBox->addWidget(m_pan); + layout->addWidget(m_pan); connect(m_pan, SIGNAL(valueChanged(int)), this, SLOT(panChanged(int))); - m_volume = new SliderGroup("Vol", 0, 100, 2, NULL); + + QHBoxLayout *volumeBox = new QHBoxLayout; + m_volume = new SliderGroup("Vol", 0, 65535, 2, NULL); volumeBox->addWidget(m_volume); connect(m_volume, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int))); + m_bus1 = new SliderGroup("Bus 1", 0, 65535, 2, NULL); + volumeBox->addWidget(m_bus1); + connect(m_bus1, SIGNAL(valueChanged(int)), this, SLOT(bus1VolumeChanged(int))); + m_bus2 = new SliderGroup("Bus 2", 0, 65535, 2, NULL); + volumeBox->addWidget(m_bus2); + connect(m_bus2, SIGNAL(valueChanged(int)), this, SLOT(bus2VolumeChanged(int))); volumeBox->setSpacing(0); volumeBox->setContentsMargins(0, 0, 0, 0); layout->addLayout(volumeBox); @@ -102,6 +105,16 @@ void AudioLayerWidget::volumeChanged(int value) emit(uiSliderChanged(m_layer, Slider::Volume, value)); } +void AudioLayerWidget::bus1VolumeChanged(int value) +{ + emit(uiSliderChanged(m_layer, Slider::Bus1, value)); +} + +void AudioLayerWidget::bus2VolumeChanged(int value) +{ + emit(uiSliderChanged(m_layer, Slider::Bus2, value)); +} + void AudioLayerWidget::panChanged(int value) { emit(uiSliderChanged(m_layer, Slider::Pan, value)); @@ -157,9 +170,9 @@ void AudioLayerWidget::openMediaDialog() // from DMX signals void AudioLayerWidget::setVol(float vol) { - m_volume->blockSignals(true); - m_volume->setValue(vol); - m_volume->blockSignals(false); + m_volume->blockSignals(true); + m_volume->setValue(vol); + m_volume->blockSignals(false); } void AudioLayerWidget::setPan(int pan) @@ -221,8 +234,17 @@ void AudioLayerWidget::setCurrentTime(float progress) void AudioLayerWidget::setFilterParam(int channel, int value) { - m_filterBank->blockSignals(true); - m_filterBank->setValue(channel, value); - m_filterBank->blockSignals(false); - + if (channel <= FILTER_BANK_GAIN - FILTER_CHANNELS){ + m_filterBank->blockSignals(true); + m_filterBank->setValue(channel, value); + m_filterBank->blockSignals(false); + } else if (channel == SEND1 - HP_FREQ) { + m_bus1->blockSignals(false); + m_bus1->setValue((value * 256) + 255); + m_bus1->blockSignals(true); + } else if (channel == SEND2 - HP_FREQ) { + m_bus2->blockSignals(false); + m_bus2->setValue(value * 256 + 255); + m_bus2->blockSignals(true); + } } diff --git a/src/audiolayerwidget.h b/src/audiolayerwidget.h index f3ba1e4..cb446a9 100644 --- a/src/audiolayerwidget.h +++ b/src/audiolayerwidget.h @@ -39,6 +39,8 @@ private: SliderGroup *m_volume; SliderGroup *m_pan; SliderGroup *m_pitch; + SliderGroup *m_bus1; + SliderGroup *m_bus2; QTimeEdit *m_progressTime; QTimeEdit *m_totalTimeValue; QProgressBar *m_progress; @@ -51,6 +53,8 @@ private slots: void openMediaDialog(); void toggleSuspendResume(); void volumeChanged(int vol); + void bus1VolumeChanged(int vol); + void bus2VolumeChanged(int vol); void panChanged(int pan); void pitchChanged(int pitch); void setBypass(bool value); diff --git a/src/audiowidget.cpp b/src/audiowidget.cpp index 2f3b634..da7c33f 100644 --- a/src/audiowidget.cpp +++ b/src/audiowidget.cpp @@ -1,6 +1,5 @@ #include "audiowidget.h" - -//#include +#include "dmxPersonality.h" AudioWidget::AudioWidget(QWidget *parent) : QWidget(parent) @@ -23,8 +22,8 @@ AudioWidget::AudioWidget(QWidget *parent) : for (int j = 0; j < FILTER_CHANNELS; j++) m_filtersUpdate[i][j] = -1; } - m_layout->setSpacing(0); - m_layout->setContentsMargins(1, 1, 1, 1); + m_layout->setSpacing(2); + m_layout->setContentsMargins(2, 2, 2, 2); setLayout(m_layout); m_refreshUi = new QTimer(this); connect(m_refreshUi, SIGNAL(timeout()), this, SLOT(refreshUi())); @@ -110,6 +109,6 @@ void AudioWidget::refreshUi() void AudioWidget::filterParamChanged(int layer, int channel, int value) { - m_filtersUpdate[layer][channel - 9] = value; + m_filtersUpdate[layer][channel - HP_FREQ] = value; m_layerUpdate[layer].updated = true; } diff --git a/src/defines.h b/src/defines.h index 5f73abe..8d81a59 100644 --- a/src/defines.h +++ b/src/defines.h @@ -10,9 +10,9 @@ #define FORMAT ma_format_f32 /* Must always be f32. */ #define CHANNELS 2 #define SAMPLE_RATE 48000 -#define UI_REFRESH_TIME 100 +#define UI_REFRESH_TIME 97 #define FADE_TIME 25 // DMX Frame time, 40 fps, avoid clicks -#define FILTER_CHANNELS 13 // number of dmx channels dedicated to filters by layer +#define FILTER_CHANNELS 16 // number of dmx channels dedicated to filters by layer struct dmxSetting { int address; @@ -38,7 +38,9 @@ enum Slider Volume, Pan, Pitch, - Bypass + Bypass, + Bus1, + Bus2 }; #ifdef __cplusplus @@ -71,6 +73,8 @@ struct layerData { int address; unsigned int universe; int device; + int bus1Vol; + int bus2Vol; }; #endif // __cplusplus #endif // DEFINES_H diff --git a/src/dmxPersonality.h b/src/dmxPersonality.h index 1da964a..d08671a 100644 --- a/src/dmxPersonality.h +++ b/src/dmxPersonality.h @@ -23,7 +23,7 @@ #define HIGH_FREQ 19 #define HIGH_Q 20 #define HIGH_GAIN 21 -#define FILTER_BANK_GAIN 22 // not implemented yet +#define FILTER_BANK_GAIN 22 #define SEND1 23 #define SEND2 24 #define LAYER_CHANNELS 25 diff --git a/src/filterbankwidget.cpp b/src/filterbankwidget.cpp index c9b107d..4742af2 100644 --- a/src/filterbankwidget.cpp +++ b/src/filterbankwidget.cpp @@ -86,7 +86,8 @@ void FilterBankWidget::setValue(int filter, int value) result = (double)( value / 32.0f) + 0.1f; } else if (channel == HIGH_GAIN) { result = (double)(value / 21.25) - 6.023528412f; - } + } else + result = (double)value; fb[filter]->setValue(result); } diff --git a/src/libremediaserver-audio.cpp b/src/libremediaserver-audio.cpp index 72398ee..07e3b0e 100644 --- a/src/libremediaserver-audio.cpp +++ b/src/libremediaserver-audio.cpp @@ -96,9 +96,8 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value) QString mediaFile = NULL; int aux; if (channel == VOLUME_COARSE || channel == VOLUME_FINE) { - float tmp = value / 65025.0f; - m_mae.volChanged(layer, tmp); - m_updateUi[layer][0] = tmp * 100.0f; + m_mae.volChanged(layer, value); + m_updateUi[layer][0] = value; } else if (channel == PAN) { m_mae.panChanged(layer, value); m_updateUi[layer][1] = value; @@ -236,7 +235,7 @@ void libreMediaServerAudio::uiSliderChanged(int layer, Slider s, int value) { switch (s){ case Slider::Volume: - m_mae.volChanged(layer, float((value / 100.0f))); + m_mae.volChanged(layer, value); break; case Slider::Pan: m_mae.panChanged(layer, value); @@ -246,6 +245,13 @@ void libreMediaServerAudio::uiSliderChanged(int layer, Slider s, int value) break; case Slider::Bypass: m_mae.setBypass(m_dmxSettings.at(layer).audioDevice, layer, value); + break; + case Slider::Bus1: + m_mae.filterParamChanged(layer, m_dmxSettings.at(layer).audioDevice, SEND1, value / 255); + break; + case Slider::Bus2: + m_mae.filterParamChanged(layer, m_dmxSettings.at(layer).audioDevice, SEND2, value / 255); + break; } } diff --git a/src/miniaudioengine.cpp b/src/miniaudioengine.cpp index 0599fcc..328e738 100644 --- a/src/miniaudioengine.cpp +++ b/src/miniaudioengine.cpp @@ -413,14 +413,17 @@ ma_result MiniAudioEngine::printFormatInfo(int layer) return result; } -// Expects between 0 and 1 vol value -void MiniAudioEngine::volChanged(int layer, float vol) +// Expects between 0 and 65535 vol value +void MiniAudioEngine::volChanged(int layer, int vol) { if (m_mae.mediaLoaded[layer] == false) return; - if (vol >= 1) - vol = 0.99f; - ma_sound_group_set_fade_in_milliseconds(&m_mae.sounds[layer], -1, pow(vol, 2), FADE_TIME); + float db = ((float)vol / 771.0f) - 85.0f; + if (db <= -85.0f) { + db = 0; + } else + db = ma_volume_db_to_linear(db); + ma_sound_group_set_fade_in_milliseconds(&m_mae.sounds[layer], -1, db, FADE_TIME); m_mae.currentStatus[layer].vol = vol; } @@ -618,13 +621,23 @@ ma_result MiniAudioEngine::filterParamChanged(int layer, int audioDevice, int ch return result; } } else if (channel == SEND1) { - ma_node_set_output_bus_volume(&fb->output, 0, pow((value / 255.0f), 2)); + float db = ((float)value / 3.0f) - 85.0f; + if (db <= -85.0f) { + db = 0; + } else + db = ma_volume_db_to_linear(db); + ma_node_set_output_bus_volume(&fb->output, 0, db); if (result != MA_SUCCESS) { cout << "ERROR " << result << ": Failed set Send 1 Volume." << endl; return result; } } else if (channel == SEND2) { - ma_node_set_output_bus_volume(&fb->output, 1, pow((value / 255.0f), 2)); + float db = ((float)value / 3.0f) - 85.0f; + if (db <= -85.0f) { + db = 0; + } else + db = ma_volume_db_to_linear(db); + ma_node_set_output_bus_volume(&fb->output, 1, db); if (result != MA_SUCCESS) { cout << "ERROR " << result << ": Failed set Send 2 Volume." << endl; } diff --git a/src/miniaudioengine.h b/src/miniaudioengine.h index 308706b..870dc42 100644 --- a/src/miniaudioengine.h +++ b/src/miniaudioengine.h @@ -66,7 +66,7 @@ public: protected: ma_result loadMedia(int layer, char *media, uint audioDevice); - void volChanged(int layer, float vol); + void volChanged(int layer, int vol); void panChanged(int layer, float pan); void pitchChanged(int layer, float pitch); ma_result playbackChanged(int layer, Status status); diff --git a/src/slidergroup.cpp b/src/slidergroup.cpp index 55bfcf7..9eedb70 100644 --- a/src/slidergroup.cpp +++ b/src/slidergroup.cpp @@ -39,9 +39,10 @@ SliderGroup::SliderGroup(QString name, valueBox.setFocusPolicy(Qt::NoFocus); valueBox.setButtonSymbols(QAbstractSpinBox::NoButtons); valueBox.setMinimumWidth(50); - if (decimals) - valueBox.setRange(-100, 100); - else + if (decimals) { + valueBox.setRange(-84.0f, 0.0f); + valueBox.setSpecialValueText("-inf"); + } else valueBox.setRange(min, max); valueBox.setValue(0); valueBox.setDecimals(decimals); @@ -66,20 +67,27 @@ SliderGroup::SliderGroup(QString name, void SliderGroup::sliderValueChanged(int value) { valueBox.blockSignals(true); - valueBox.setValue(value); + float db = ((float)value / 771.0f) - 85.0f; + if (db <= -84.5f) { + valueBox.setSpecialValueText("-inf"); + } else + valueBox.setValue(db); valueBox.blockSignals(false); emit valueChanged(value); }; void SliderGroup::setValue(float value) { + float db; + slider.blockSignals(true); valueBox.blockSignals(true); if (int(value) != slider.value()) slider.setValue(value); - if (valueBox.decimals()) - valueBox.setValue(value - 100.0f); - else + if (valueBox.decimals()) { + db = (float)(value / 771.0f) - 85.0f; + valueBox.setValue(db); + } else valueBox.setValue(value); slider.blockSignals(false); valueBox.blockSignals(false);