Move channel buffers from stack to structs so theyt can be reused when mixing with...
[jack_mixer.git] / jack_mixer.c
blob06dd2b3d7fcdb3d6e1127d1cafe1da37f6d9aeaa
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
4 * This file is part of jack_mixer
5 *
6 * Copyright (C) 2006 Nedko Arnaudov <nedko@arnaudov.name>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *****************************************************************************/
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdbool.h>
26 #include <math.h>
27 #include <jack/jack.h>
28 #include <jack/midiport.h>
29 #include <assert.h>
30 #include <pthread.h>
32 #include "jack_mixer.h"
33 #include "list.h"
34 //#define LOG_LEVEL LOG_LEVEL_DEBUG
35 #include "log.h"
37 #define PEAK_FRAMES_CHUNK 4800
39 #define FLOAT_EXISTS(x) (!((x) - (x)))
41 struct channel
43 struct list_head siblings;
44 struct jack_mixer * mixer_ptr;
45 char * name;
46 bool stereo;
47 float volume;
48 float balance;
49 bool muted;
50 bool soloed;
51 float volume_left;
52 float volume_right;
53 float meter_left;
54 float meter_right;
55 float abspeak;
56 jack_port_t * port_left;
57 jack_port_t * port_right;
59 jack_nframes_t peak_frames;
60 float peak_left;
61 float peak_right;
63 bool NaN_detected;
65 struct channel ** cc_map_volume_ptr_ptr;
66 struct channel ** cc_map_balance_ptr_ptr;
68 jack_default_audio_sample_t * left_buffer_ptr;
69 jack_default_audio_sample_t * right_buffer_ptr;
72 struct jack_mixer
74 pthread_mutex_t mutex;
75 jack_client_t * jack_client;
76 struct list_head channels_list;
77 struct channel main_mix_channel;
78 unsigned int channels_count;
79 unsigned int soloed_channels_count;
81 jack_port_t * port_midi_in;
82 jack_port_t * port_midi_out;
84 struct
86 bool balance; /* volume or balance is controlled by this mapping */
87 struct channel * channel_ptr;
88 } midi_cc_map[128];
91 float value_to_db(float value)
93 if (value <= 0)
95 return -INFINITY;
98 return 20.0 * log10f(value);
101 float db_to_value(float db)
103 return powf(10.0, db/20.0);
106 void
107 calc_channel_volumes(struct channel * channel_ptr)
109 if (channel_ptr->muted)
111 channel_ptr->volume_left = 0;
112 channel_ptr->volume_right = 0;
113 return;
116 if (channel_ptr->mixer_ptr->soloed_channels_count > 0 && !channel_ptr->soloed) /* there are soloed channels but we are not one of them */
118 channel_ptr->volume_left = 0;
119 channel_ptr->volume_right = 0;
120 return;
123 if (channel_ptr->stereo)
125 if (channel_ptr->balance > 0)
127 channel_ptr->volume_left = channel_ptr->volume * (1 - channel_ptr->balance);
128 channel_ptr->volume_right = channel_ptr->volume;
130 else
132 channel_ptr->volume_left = channel_ptr->volume;
133 channel_ptr->volume_right = channel_ptr->volume * (1 + channel_ptr->balance);
136 else
138 channel_ptr->volume_left = channel_ptr->volume * (1 - channel_ptr->balance);
139 channel_ptr->volume_right = channel_ptr->volume * (1 + channel_ptr->balance);
143 void
144 calc_all_channel_volumes(
145 struct jack_mixer * mixer_ptr)
147 struct list_head * node_ptr;
148 struct channel * channel_ptr;
150 list_for_each(node_ptr, &mixer_ptr->channels_list)
152 channel_ptr = list_entry(node_ptr, struct channel, siblings);
153 calc_channel_volumes(channel_ptr);
157 #define channel_ptr ((struct channel *)channel)
159 const char * channel_get_name(jack_mixer_channel_t channel)
161 return channel_ptr->name;
164 void channel_rename(jack_mixer_channel_t channel, const char * name)
166 char * new_name;
167 size_t channel_name_size;
168 char * port_name;
169 int ret;
171 new_name = strdup(name);
172 if (new_name == NULL)
174 return;
177 if (channel_ptr->name)
179 free(channel_ptr->name);
182 channel_ptr->name = new_name;
184 if (channel_ptr->stereo)
186 channel_name_size = strlen(name);
187 port_name = malloc(channel_name_size + 3);
188 memcpy(port_name, name, channel_name_size);
190 port_name[channel_name_size] = ' ';
191 port_name[channel_name_size+1] = 'L';
192 port_name[channel_name_size+2] = 0;
194 ret = jack_port_set_name(channel_ptr->port_left, port_name);
195 if (ret != 0)
197 /* what could we do here? */
200 port_name[channel_name_size+1] = 'R';
202 ret = jack_port_set_name(channel_ptr->port_right, port_name);
203 if (ret != 0)
205 /* what could we do here? */
208 free(port_name);
210 else
212 ret = jack_port_set_name(channel_ptr->port_left, name);
213 if (ret != 0)
215 /* what could we do here? */
220 bool channel_is_stereo(jack_mixer_channel_t channel)
222 return channel_ptr->stereo;
225 void remove_channel(jack_mixer_channel_t channel)
227 list_del(&channel_ptr->siblings);
228 free(channel_ptr->name);
230 jack_port_unregister(channel_ptr->mixer_ptr->jack_client, channel_ptr->port_left);
231 if (channel_ptr->stereo)
233 jack_port_unregister(channel_ptr->mixer_ptr->jack_client, channel_ptr->port_right);
236 channel_ptr->mixer_ptr->channels_count--;
238 if (channel_ptr->cc_map_volume_ptr_ptr != NULL)
240 assert(*(channel_ptr->cc_map_volume_ptr_ptr) == channel_ptr);
241 *(channel_ptr->cc_map_volume_ptr_ptr) = NULL;
244 if (channel_ptr->cc_map_balance_ptr_ptr != NULL)
246 assert(*(channel_ptr->cc_map_balance_ptr_ptr) == channel_ptr);
247 *(channel_ptr->cc_map_balance_ptr_ptr) = NULL;
250 free(channel_ptr);
253 void channel_stereo_meter_read(jack_mixer_channel_t channel, double * left_ptr, double * right_ptr)
255 *left_ptr = value_to_db(channel_ptr->meter_left);
256 *right_ptr = value_to_db(channel_ptr->meter_right);
259 void channel_mono_meter_read(jack_mixer_channel_t channel, double * mono_ptr)
261 *mono_ptr = value_to_db(channel_ptr->meter_left);
264 void channel_volume_write(jack_mixer_channel_t channel, double volume)
266 channel_ptr->volume = db_to_value(volume);
267 calc_channel_volumes(channel_ptr);
270 void channel_balance_write(jack_mixer_channel_t channel, double balance)
272 channel_ptr->balance = balance;
273 calc_channel_volumes(channel_ptr);
276 double channel_abspeak_read(jack_mixer_channel_t channel)
278 if (channel_ptr->NaN_detected)
280 return sqrt(-1);
282 else
284 return value_to_db(channel_ptr->abspeak);
288 void channel_abspeak_reset(jack_mixer_channel_t channel)
290 channel_ptr->abspeak = 0;
291 channel_ptr->NaN_detected = false;
294 void channel_mute(jack_mixer_channel_t channel)
296 channel_ptr->muted = true;
297 calc_channel_volumes(channel_ptr);
300 void channel_unmute(jack_mixer_channel_t channel)
302 channel_ptr->muted = false;
303 calc_channel_volumes(channel_ptr);
306 void channel_solo(jack_mixer_channel_t channel)
308 if (!channel_ptr->soloed)
310 channel_ptr->soloed = true;
311 channel_ptr->mixer_ptr->soloed_channels_count++;
313 if (channel_ptr->mixer_ptr->soloed_channels_count == 1)
315 calc_all_channel_volumes(channel_ptr->mixer_ptr);
317 else
319 calc_channel_volumes(channel_ptr);
324 void channel_unsolo(jack_mixer_channel_t channel)
326 if (channel_ptr->soloed)
328 channel_ptr->soloed = false;
329 channel_ptr->mixer_ptr->soloed_channels_count--;
331 if (channel_ptr->mixer_ptr->soloed_channels_count == 0)
333 calc_all_channel_volumes(channel_ptr->mixer_ptr);
335 else
337 calc_channel_volumes(channel_ptr);
342 bool channel_is_muted(jack_mixer_channel_t channel)
344 return channel_ptr->muted;
347 bool channel_is_soloed(jack_mixer_channel_t channel)
349 return channel_ptr->soloed;
352 #undef channel_ptr
354 static
355 inline
356 void
357 mix(
358 struct jack_mixer * mixer_ptr,
359 jack_nframes_t start,
360 jack_nframes_t count)
364 static
365 inline
366 void
367 update_channel_buffers(
368 struct channel * channel_ptr,
369 jack_nframes_t nframes)
371 channel_ptr->left_buffer_ptr = jack_port_get_buffer(channel_ptr->port_left, nframes);
373 if (channel_ptr->stereo)
375 channel_ptr->right_buffer_ptr = jack_port_get_buffer(channel_ptr->port_right, nframes);
379 #define mixer_ptr ((struct jack_mixer *)context)
382 process(jack_nframes_t nframes, void * context)
384 jack_nframes_t i;
385 struct list_head * node_ptr;
386 struct channel * channel_ptr;
387 jack_default_audio_sample_t frame_left;
388 jack_default_audio_sample_t frame_right;
389 jack_nframes_t event_count;
390 jack_midi_event_t in_event;
391 void * midi_buffer;
393 update_channel_buffers(&mixer_ptr->main_mix_channel, nframes);
395 for (i = 0 ; i < nframes ; i++)
397 mixer_ptr->main_mix_channel.left_buffer_ptr[i] = 0.0;
398 mixer_ptr->main_mix_channel.right_buffer_ptr[i] = 0.0;
401 midi_buffer = jack_port_get_buffer(mixer_ptr->port_midi_in, nframes);
402 event_count = jack_midi_get_event_count(midi_buffer);
404 for (i = 0 ; i < event_count; i++)
406 jack_midi_event_get(&in_event, midi_buffer, i);
408 if (in_event.size != 3 ||
409 (in_event.buffer[0] & 0xF0) != 0xB0 ||
410 in_event.buffer[1] > 127 ||
411 in_event.buffer[2] > 127)
413 continue;
416 LOG_DEBUG(
417 "%u: CC#%u -> %u",
418 (unsigned int)(in_event.buffer[0] & 0x0F),
419 (unsigned int)in_event.buffer[1],
420 (unsigned int)in_event.buffer[2]);
422 channel_ptr = mixer_ptr->midi_cc_map[in_event.buffer[1]].channel_ptr;
423 if (channel_ptr != NULL) /* if we have mapping for particular CC */
425 if (mixer_ptr->midi_cc_map[in_event.buffer[1]].balance)
427 channel_ptr->balance = ((float)in_event.buffer[2] / 127 - 0.5) * 2;
428 LOG_DEBUG("\"%s\" volume -> %f", channel_ptr->name, channel_ptr->balance);
430 else
432 channel_ptr->volume = (float)in_event.buffer[2] / 127;
434 LOG_DEBUG("\"%s\" volume -> %f", channel_ptr->name, channel_ptr->volume);
437 calc_channel_volumes(channel_ptr);
441 /* process input channels and mix them into main mix */
442 list_for_each(node_ptr, &mixer_ptr->channels_list)
444 channel_ptr = list_entry(node_ptr, struct channel, siblings);
446 update_channel_buffers(channel_ptr, nframes);
448 for (i = 0 ; i < nframes ; i++)
450 if (!FLOAT_EXISTS(channel_ptr->left_buffer_ptr[i]))
452 channel_ptr->NaN_detected = true;
453 break;
456 frame_left = channel_ptr->left_buffer_ptr[i] * channel_ptr->volume_left;
457 mixer_ptr->main_mix_channel.left_buffer_ptr[i] += frame_left;
459 if (channel_ptr->stereo)
461 if (!FLOAT_EXISTS(channel_ptr->right_buffer_ptr[i]))
463 channel_ptr->NaN_detected = true;
464 break;
467 frame_right = channel_ptr->right_buffer_ptr[i] * channel_ptr->volume_right;
469 else
471 frame_right = channel_ptr->left_buffer_ptr[i] * channel_ptr->volume_right;
474 mixer_ptr->main_mix_channel.right_buffer_ptr[i] += frame_right;
476 if (channel_ptr->stereo)
478 frame_left = fabsf(frame_left);
479 frame_right = fabsf(frame_right);
481 if (channel_ptr->peak_left < frame_left)
483 channel_ptr->peak_left = frame_left;
485 if (frame_left > channel_ptr->abspeak)
487 channel_ptr->abspeak = frame_left;
491 if (channel_ptr->peak_right < frame_right)
493 channel_ptr->peak_right = frame_right;
495 if (frame_right > channel_ptr->abspeak)
497 channel_ptr->abspeak = frame_right;
501 else
503 frame_left = (fabsf(frame_left) + fabsf(frame_right)) / 2;
505 if (channel_ptr->peak_left < frame_left)
507 channel_ptr->peak_left = frame_left;
509 if (frame_left > channel_ptr->abspeak)
511 channel_ptr->abspeak = frame_left;
516 channel_ptr->peak_frames++;
517 if (channel_ptr->peak_frames >= PEAK_FRAMES_CHUNK)
519 channel_ptr->meter_left = channel_ptr->peak_left;
520 channel_ptr->peak_left = 0.0;
522 if (channel_ptr->stereo)
524 channel_ptr->meter_right = channel_ptr->peak_right;
525 channel_ptr->peak_right = 0.0;
528 channel_ptr->peak_frames = 0;
533 /* process main mix channel */
534 for (i = 0 ; i < nframes ; i++)
536 mixer_ptr->main_mix_channel.left_buffer_ptr[i] *= mixer_ptr->main_mix_channel.volume_left;
537 mixer_ptr->main_mix_channel.right_buffer_ptr[i] *= mixer_ptr->main_mix_channel.volume_right;
539 frame_left = fabsf(mixer_ptr->main_mix_channel.left_buffer_ptr[i]);
540 if (mixer_ptr->main_mix_channel.peak_left < frame_left)
542 mixer_ptr->main_mix_channel.peak_left = frame_left;
544 if (frame_left > mixer_ptr->main_mix_channel.abspeak)
546 mixer_ptr->main_mix_channel.abspeak = frame_left;
550 frame_right = fabsf(mixer_ptr->main_mix_channel.right_buffer_ptr[i]);
551 if (mixer_ptr->main_mix_channel.peak_right < frame_right)
553 mixer_ptr->main_mix_channel.peak_right = frame_right;
555 if (frame_right > mixer_ptr->main_mix_channel.abspeak)
557 mixer_ptr->main_mix_channel.abspeak = frame_right;
561 mixer_ptr->main_mix_channel.peak_frames++;
562 if (mixer_ptr->main_mix_channel.peak_frames >= PEAK_FRAMES_CHUNK)
564 mixer_ptr->main_mix_channel.meter_left = mixer_ptr->main_mix_channel.peak_left;
565 mixer_ptr->main_mix_channel.peak_left = 0.0;
567 mixer_ptr->main_mix_channel.meter_right = mixer_ptr->main_mix_channel.peak_right;
568 mixer_ptr->main_mix_channel.peak_right = 0.0;
570 mixer_ptr->main_mix_channel.peak_frames = 0;
574 return 0;
577 #undef mixer_ptr
579 jack_mixer_t
580 create(
581 const char * jack_client_name_ptr)
583 int ret;
584 struct jack_mixer * mixer_ptr;
585 int i;
588 mixer_ptr = malloc(sizeof(struct jack_mixer));
589 if (mixer_ptr == NULL)
591 goto exit;
594 ret = pthread_mutex_init(&mixer_ptr->mutex, NULL);
595 if (ret != 0)
597 goto exit_free;
600 INIT_LIST_HEAD(&mixer_ptr->channels_list);
602 mixer_ptr->channels_count = 0;
603 mixer_ptr->soloed_channels_count = 0;
605 for (i = 0 ; i < 128 ; i++)
607 mixer_ptr->midi_cc_map[i].channel_ptr = NULL;
610 mixer_ptr->midi_cc_map[7].channel_ptr = &mixer_ptr->main_mix_channel;
611 mixer_ptr->midi_cc_map[7].balance = false;
612 mixer_ptr->main_mix_channel.cc_map_volume_ptr_ptr = &mixer_ptr->midi_cc_map[7].channel_ptr;
614 mixer_ptr->midi_cc_map[8].channel_ptr = &mixer_ptr->main_mix_channel;
615 mixer_ptr->midi_cc_map[8].balance = true;
616 mixer_ptr->main_mix_channel.cc_map_balance_ptr_ptr = &mixer_ptr->midi_cc_map[8].channel_ptr;
618 LOG_DEBUG("Initializing JACK");
619 mixer_ptr->jack_client = jack_client_new(jack_client_name_ptr);
620 if (mixer_ptr->jack_client == NULL)
622 LOG_ERROR("Cannot create JACK client.");
623 LOG_NOTICE("Please make sure JACK daemon is running.");
624 goto exit_destroy_mutex;
627 LOG_DEBUG("JACK client created");
629 LOG_DEBUG("Sample rate: %" PRIu32, jack_get_sample_rate(mixer_ptr->jack_client));
631 mixer_ptr->main_mix_channel.mixer_ptr = mixer_ptr;
633 mixer_ptr->port_midi_in = jack_port_register(mixer_ptr->jack_client, "midi in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
634 if (mixer_ptr->port_midi_in == NULL)
636 LOG_ERROR("Cannot create JACK port");
637 goto close_jack;
640 mixer_ptr->port_midi_out = jack_port_register(mixer_ptr->jack_client, "midi out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
641 if (mixer_ptr->port_midi_out == NULL)
643 LOG_ERROR("Cannot create JACK port");
644 goto close_jack;
647 mixer_ptr->main_mix_channel.port_left = jack_port_register(mixer_ptr->jack_client, "main out L", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
648 if (mixer_ptr->main_mix_channel.port_left == NULL)
650 LOG_ERROR("Cannot create JACK port");
651 goto close_jack;
654 mixer_ptr->main_mix_channel.port_right = jack_port_register(mixer_ptr->jack_client, "main out R", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
655 if (mixer_ptr->main_mix_channel.port_right == NULL)
657 LOG_ERROR("Cannot create JACK port");
658 goto close_jack;
661 mixer_ptr->main_mix_channel.stereo = true;
663 mixer_ptr->main_mix_channel.volume = 0.0;
664 mixer_ptr->main_mix_channel.balance = 0.0;
665 mixer_ptr->main_mix_channel.muted = false;
666 mixer_ptr->main_mix_channel.soloed = false;
667 mixer_ptr->main_mix_channel.meter_left = 0.0;
668 mixer_ptr->main_mix_channel.meter_right = 0.0;
669 mixer_ptr->main_mix_channel.abspeak = 0.0;
671 mixer_ptr->main_mix_channel.peak_left = 0.0;
672 mixer_ptr->main_mix_channel.peak_right = 0.0;
673 mixer_ptr->main_mix_channel.peak_frames = 0;
675 mixer_ptr->main_mix_channel.NaN_detected = false;
677 calc_channel_volumes(&mixer_ptr->main_mix_channel);
679 ret = jack_set_process_callback(mixer_ptr->jack_client, process, mixer_ptr);
680 if (ret != 0)
682 LOG_ERROR("Cannot set JACK process callback");
683 goto close_jack;
686 ret = jack_activate(mixer_ptr->jack_client);
687 if (ret != 0)
689 LOG_ERROR("Cannot activate JACK client");
690 goto close_jack;
693 return mixer_ptr;
695 close_jack:
696 jack_client_close(mixer_ptr->jack_client); /* this should clear all other resources we obtained through the client handle */
698 exit_destroy_mutex:
699 pthread_mutex_destroy(&mixer_ptr->mutex);
701 exit_free:
702 free(mixer_ptr);
704 exit:
705 return NULL;
708 #define mixer_ctx_ptr ((struct jack_mixer *)mixer)
710 void
711 destroy(
712 jack_mixer_t mixer)
714 LOG_DEBUG("Uninitializing JACK");
716 assert(mixer_ctx_ptr->jack_client != NULL);
718 jack_client_close(mixer_ctx_ptr->jack_client);
720 pthread_mutex_destroy(&mixer_ctx_ptr->mutex);
722 free(mixer_ctx_ptr);
725 jack_mixer_channel_t
726 get_main_mix_channel(
727 jack_mixer_t mixer)
729 return &mixer_ctx_ptr->main_mix_channel;
732 unsigned int
733 get_channels_count(
734 jack_mixer_t mixer)
736 return mixer_ctx_ptr->channels_count;
739 jack_mixer_channel_t
740 add_channel(
741 jack_mixer_t mixer,
742 const char * channel_name,
743 bool stereo)
745 struct channel * channel_ptr;
746 char * port_name;
747 size_t channel_name_size;
748 int i;
750 channel_ptr = malloc(sizeof(struct channel));
751 if (channel_ptr == NULL)
753 goto exit;
756 channel_ptr->mixer_ptr = mixer_ctx_ptr;
758 channel_ptr->name = strdup(channel_name);
759 if (channel_ptr->name == NULL)
761 goto exit_free_channel;
764 if (stereo)
766 channel_name_size = strlen(channel_name);
767 port_name = malloc(channel_name_size + 3);
768 memcpy(port_name, channel_name, channel_name_size);
769 port_name[channel_name_size] = ' ';
770 port_name[channel_name_size+1] = 'L';
771 port_name[channel_name_size+2] = 0;
772 channel_ptr->port_left = jack_port_register(channel_ptr->mixer_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
773 port_name[channel_name_size+1] = 'R';
774 channel_ptr->port_right = jack_port_register(channel_ptr->mixer_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
775 free(port_name);
777 else
779 channel_ptr->port_left = jack_port_register(channel_ptr->mixer_ptr->jack_client, channel_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
782 channel_ptr->stereo = stereo;
784 channel_ptr->volume = 0.0;
785 channel_ptr->balance = 0.0;
786 channel_ptr->muted = false;
787 channel_ptr->soloed = false;
788 channel_ptr->meter_left = -1.0;
789 channel_ptr->meter_right = -1.0;
790 channel_ptr->abspeak = 0.0;
792 channel_ptr->peak_left = 0.0;
793 channel_ptr->peak_right = 0.0;
794 channel_ptr->peak_frames = 0;
796 channel_ptr->NaN_detected = false;
798 calc_channel_volumes(channel_ptr);
800 list_add_tail(&channel_ptr->siblings, &channel_ptr->mixer_ptr->channels_list);
801 channel_ptr->mixer_ptr->channels_count++;
803 for (i = 11 ; i < 128 ; i++)
805 if (mixer_ctx_ptr->midi_cc_map[i].channel_ptr == NULL)
807 mixer_ctx_ptr->midi_cc_map[i].channel_ptr = channel_ptr;
808 mixer_ctx_ptr->midi_cc_map[i].balance = false;
809 channel_ptr->cc_map_volume_ptr_ptr = &mixer_ctx_ptr->midi_cc_map[i].channel_ptr;
811 LOG_NOTICE("New channel \"%s\" volume mapped to CC#%i", channel_name, i);
813 break;
817 for (; i < 128 ; i++)
819 if (mixer_ctx_ptr->midi_cc_map[i].channel_ptr == NULL)
821 mixer_ctx_ptr->midi_cc_map[i].channel_ptr = channel_ptr;
822 mixer_ctx_ptr->midi_cc_map[i].balance = true;
823 channel_ptr->cc_map_balance_ptr_ptr = &mixer_ctx_ptr->midi_cc_map[i].channel_ptr;
825 LOG_NOTICE("New channel \"%s\" balance mapped to CC#%i", channel_name, i);
827 break;
831 goto exit;
833 exit_free_channel:
834 free(channel_ptr);
836 exit:
837 return channel_ptr;