]> git.0d.be Git - jack_mixer.git/blob - scale.c
Set version to 14 in preparation for next release
[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   scale_remove_thresholds(scale);
75   free(scale_ptr);
76 }
77
78 void 
79 scale_remove_thresholds(
80   jack_mixer_scale_t scale)
81 {
82   
83   struct threshold * threshold_ptr;
84   struct threshold * node_ptr;
85
86   list_for_each_entry_safe(threshold_ptr, node_ptr, &scale_ptr->thresholds, scale_siblings)
87   {
88     list_del(&(threshold_ptr->scale_siblings));
89     free(threshold_ptr);
90     threshold_ptr = NULL;
91   }
92 }
93
94 bool
95 scale_add_threshold(
96   jack_mixer_scale_t scale,
97   float db,
98   float scale_value)
99 {
100   struct threshold * threshold_ptr;
101
102   LOG_DEBUG("Adding threshold (%f dBFS -> %f) to scale %p", db, scale, scale_ptr);
103
104   threshold_ptr = malloc(sizeof(struct threshold));
105   LOG_DEBUG("Threshold %p created ", threshold_ptr, db, scale);
106
107   if (threshold_ptr == NULL)
108   {
109     return false;
110   }
111
112   threshold_ptr->db = db;
113   threshold_ptr->scale = scale_value;
114
115   list_add_tail(&threshold_ptr->scale_siblings, &scale_ptr->thresholds);
116
117   if (db > scale_ptr->max_db)
118   {
119     scale_ptr->max_db = db;
120   }
121
122   return true;
123 }
124
125 #undef threshold_ptr
126
127 void
128 scale_calculate_coefficients(
129   jack_mixer_scale_t scale)
130 {
131   struct threshold * threshold_ptr;
132   struct threshold * prev_ptr;
133   struct list_head * node_ptr;
134
135   prev_ptr = NULL;
136
137   list_for_each(node_ptr, &scale_ptr->thresholds)
138   {
139     threshold_ptr = list_entry(node_ptr, struct threshold, scale_siblings);
140
141     LOG_DEBUG("Calculating coefficients for threshold %p", threshold_ptr);
142
143     if (prev_ptr != NULL)
144     {
145       threshold_ptr->a = (prev_ptr->scale - threshold_ptr->scale) / (prev_ptr->db - threshold_ptr->db);
146       threshold_ptr->b = threshold_ptr->scale - threshold_ptr->a * threshold_ptr->db;
147       LOG_DEBUG("%.0f dB - %.0f dB: scale = %f * dB + %f", prev_ptr->db, threshold_ptr->db, threshold_ptr->a, threshold_ptr->b);
148     }
149
150     prev_ptr = threshold_ptr;
151   }
152 }
153
154 /* Convert dBFS value to number in range 0.0-1.0 */
155 double
156 scale_db_to_scale(
157   jack_mixer_scale_t scale,
158   double db)
159 {
160   struct threshold * threshold_ptr;
161   struct threshold * prev_ptr;
162   struct list_head * node_ptr;
163
164   prev_ptr = NULL;
165
166   list_for_each(node_ptr, &scale_ptr->thresholds)
167   {
168     threshold_ptr = list_entry(node_ptr, struct threshold, scale_siblings);
169
170     if (db < threshold_ptr->db)
171     {
172       LOG_DEBUG("Match at %f dB treshold", threshold_ptr->db);
173       if (prev_ptr == NULL)
174       {
175         return 0.0;
176       }
177
178       return threshold_ptr->a * db + threshold_ptr->b;
179     }
180
181     prev_ptr = threshold_ptr;
182   }
183
184   return 1.0;
185 }
186
187 /* Convert number in range 0.0-1.0 to dBFS value */
188 double
189 scale_scale_to_db(
190   jack_mixer_scale_t scale,
191   double scale_value)
192 {
193   struct threshold * threshold_ptr;
194   struct threshold * prev_ptr;
195   struct list_head * node_ptr;
196
197   prev_ptr = NULL;
198
199   list_for_each(node_ptr, &scale_ptr->thresholds)
200   {
201     threshold_ptr = list_entry(node_ptr, struct threshold, scale_siblings);
202
203     if (scale_value <= threshold_ptr->scale)
204     {
205       if (prev_ptr == NULL)
206       {
207         return -INFINITY;
208       }
209
210       return (scale_value - threshold_ptr->b) / threshold_ptr->a;
211     }
212
213     prev_ptr = threshold_ptr;
214   }
215
216   return scale_ptr->max_db;
217 }