]> git.0d.be Git - jack_mixer.git/blob - scale.c
Guard Channel_set_volume() against unitialized channel
[jack_mixer.git] / scale.c
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
3  *
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
11  *
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.
16  *
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.
20  *
21  *****************************************************************************/
22
23 #include <stddef.h>
24 #include <stdbool.h>
25 #include <stdlib.h>
26 #include <math.h>
27 #include <assert.h>
28
29 #include "jack_mixer.h"
30 //#define LOG_LEVEL LOG_LEVEL_DEBUG
31 #include "log.h"
32 #include "list.h"
33
34 struct threshold
35 {
36   struct list_head scale_siblings;
37   double db;
38   double scale;
39   double a;
40   double b;
41 };
42
43 struct scale
44 {
45   struct list_head thresholds;
46   double max_db;
47 };
48
49 jack_mixer_scale_t
50 scale_create()
51 {
52   struct scale * scale_ptr;
53
54   scale_ptr = malloc(sizeof(struct scale));
55   if (scale_ptr == NULL)
56   {
57     return NULL;
58   }
59
60   INIT_LIST_HEAD(&scale_ptr->thresholds);
61   scale_ptr->max_db = -INFINITY;
62
63   LOG_DEBUG("Scale %p created", scale_ptr);
64
65   return (jack_mixer_scale_t)scale_ptr;
66 }
67
68 #define scale_ptr ((struct scale *)scale)
69
70 void
71 scale_destroy(
72   jack_mixer_scale_t scale)
73 {
74   free(scale_ptr);
75 }
76
77 bool
78 scale_add_threshold(
79   jack_mixer_scale_t scale,
80   float db,
81   float scale_value)
82 {
83   struct threshold * threshold_ptr;
84
85   LOG_DEBUG("Adding threshold (%f dBFS -> %f) to scale %p", db, scale, scale_ptr);
86   LOG_DEBUG("Threshold %p created ", threshold_ptr, db, scale);
87
88   threshold_ptr = malloc(sizeof(struct threshold));
89   if (threshold_ptr == NULL)
90   {
91     return false;
92   }
93
94   threshold_ptr->db = db;
95   threshold_ptr->scale = scale_value;
96
97   list_add_tail(&threshold_ptr->scale_siblings, &scale_ptr->thresholds);
98
99   if (db > scale_ptr->max_db)
100   {
101     scale_ptr->max_db = db;
102   }
103
104   return true;
105 }
106
107 #undef threshold_ptr
108
109 void
110 scale_calculate_coefficients(
111   jack_mixer_scale_t scale)
112 {
113   struct threshold * threshold_ptr;
114   struct threshold * prev_ptr;
115   struct list_head * node_ptr;
116
117   prev_ptr = NULL;
118
119   list_for_each(node_ptr, &scale_ptr->thresholds)
120   {
121     threshold_ptr = list_entry(node_ptr, struct threshold, scale_siblings);
122
123     LOG_DEBUG("Calculating coefficients for threshold %p", threshold_ptr);
124
125     if (prev_ptr != NULL)
126     {
127       threshold_ptr->a = (prev_ptr->scale - threshold_ptr->scale) / (prev_ptr->db - threshold_ptr->db);
128       threshold_ptr->b = threshold_ptr->scale - threshold_ptr->a * threshold_ptr->db;
129       LOG_DEBUG("%.0f dB - %.0f dB: scale = %f * dB + %f", prev_ptr->db, threshold_ptr->db, threshold_ptr->a, threshold_ptr->b);
130     }
131
132     prev_ptr = threshold_ptr;
133   }
134 }
135
136 /* Convert dBFS value to number in range 0.0-1.0 */
137 double
138 scale_db_to_scale(
139   jack_mixer_scale_t scale,
140   double db)
141 {
142   struct threshold * threshold_ptr;
143   struct threshold * prev_ptr;
144   struct list_head * node_ptr;
145
146   prev_ptr = NULL;
147
148   list_for_each(node_ptr, &scale_ptr->thresholds)
149   {
150     threshold_ptr = list_entry(node_ptr, struct threshold, scale_siblings);
151
152     if (db < threshold_ptr->db)
153     {
154       LOG_DEBUG("Match at %f dB treshold", threshold_ptr->db);
155       if (prev_ptr == NULL)
156       {
157         return 0.0;
158       }
159
160       return threshold_ptr->a * db + threshold_ptr->b;
161     }
162
163     prev_ptr = threshold_ptr;
164   }
165
166   return 1.0;
167 }
168
169 /* Convert number in range 0.0-1.0 to dBFS value */
170 double
171 scale_scale_to_db(
172   jack_mixer_scale_t scale,
173   double scale_value)
174 {
175   struct threshold * threshold_ptr;
176   struct threshold * prev_ptr;
177   struct list_head * node_ptr;
178
179   prev_ptr = NULL;
180
181   list_for_each(node_ptr, &scale_ptr->thresholds)
182   {
183     threshold_ptr = list_entry(node_ptr, struct threshold, scale_siblings);
184
185     if (scale_value <= threshold_ptr->scale)
186     {
187       if (prev_ptr == NULL)
188       {
189         return -INFINITY;
190       }
191
192       return (scale_value - threshold_ptr->b) / threshold_ptr->a;
193     }
194
195     prev_ptr = threshold_ptr;
196   }
197
198   return scale_ptr->max_db;
199 }