1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <pulse/xmalloc.h>
25 #include <math.h>
26
27 #include <pulsecore/resampler.h>
28
29 struct peaks_data { /* data specific to the peak finder pseudo resampler */
30 unsigned o_counter;
31 unsigned i_counter;
32
33 float max_f[PA_CHANNELS_MAX];
34 int16_t max_i[PA_CHANNELS_MAX];
35 };
36
peaks_resample(pa_resampler * r,const pa_memchunk * input,unsigned in_n_frames,pa_memchunk * output,unsigned * out_n_frames)37 static unsigned peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
38 unsigned c, o_index = 0;
39 unsigned i, i_end = 0;
40 void *src, *dst;
41 struct peaks_data *peaks_data;
42
43 pa_assert(r);
44 pa_assert(input);
45 pa_assert(output);
46 pa_assert(out_n_frames);
47
48 peaks_data = r->impl.data;
49 src = pa_memblock_acquire_chunk(input);
50 dst = pa_memblock_acquire_chunk(output);
51
52 i = ((uint64_t) peaks_data->o_counter * r->i_ss.rate) / r->o_ss.rate;
53 i = i > peaks_data->i_counter ? i - peaks_data->i_counter : 0;
54
55 while (i_end < in_n_frames) {
56 i_end = ((uint64_t) (peaks_data->o_counter + 1) * r->i_ss.rate) / r->o_ss.rate;
57 i_end = i_end > peaks_data->i_counter ? i_end - peaks_data->i_counter : 0;
58
59 pa_assert_fp(o_index * r->w_fz < pa_memblock_get_length(output->memblock));
60
61 /* 1ch float is treated separately, because that is the common case */
62 if (r->work_channels == 1 && r->work_format == PA_SAMPLE_FLOAT32NE) {
63 float *s = (float*) src + i;
64 float *d = (float*) dst + o_index;
65
66 for (; i < i_end && i < in_n_frames; i++) {
67 float n = fabsf(*s++);
68
69 if (n > peaks_data->max_f[0])
70 peaks_data->max_f[0] = n;
71 }
72
73 if (i == i_end) {
74 *d = peaks_data->max_f[0];
75 peaks_data->max_f[0] = 0;
76 o_index++, peaks_data->o_counter++;
77 }
78 } else if (r->work_format == PA_SAMPLE_S16NE) {
79 int16_t *s = (int16_t*) src + r->work_channels * i;
80 int16_t *d = (int16_t*) dst + r->work_channels * o_index;
81
82 for (; i < i_end && i < in_n_frames; i++)
83 for (c = 0; c < r->work_channels; c++) {
84 int16_t n = abs(*s++);
85
86 if (n > peaks_data->max_i[c])
87 peaks_data->max_i[c] = n;
88 }
89
90 if (i == i_end) {
91 for (c = 0; c < r->work_channels; c++, d++) {
92 *d = peaks_data->max_i[c];
93 peaks_data->max_i[c] = 0;
94 }
95 o_index++, peaks_data->o_counter++;
96 }
97 } else {
98 float *s = (float*) src + r->work_channels * i;
99 float *d = (float*) dst + r->work_channels * o_index;
100
101 for (; i < i_end && i < in_n_frames; i++)
102 for (c = 0; c < r->work_channels; c++) {
103 float n = fabsf(*s++);
104
105 if (n > peaks_data->max_f[c])
106 peaks_data->max_f[c] = n;
107 }
108
109 if (i == i_end) {
110 for (c = 0; c < r->work_channels; c++, d++) {
111 *d = peaks_data->max_f[c];
112 peaks_data->max_f[c] = 0;
113 }
114 o_index++, peaks_data->o_counter++;
115 }
116 }
117 }
118
119 pa_memblock_release(input->memblock);
120 pa_memblock_release(output->memblock);
121
122 *out_n_frames = o_index;
123
124 peaks_data->i_counter += in_n_frames;
125
126 /* Normalize counters */
127 while (peaks_data->i_counter >= r->i_ss.rate) {
128 pa_assert(peaks_data->o_counter >= r->o_ss.rate);
129
130 peaks_data->i_counter -= r->i_ss.rate;
131 peaks_data->o_counter -= r->o_ss.rate;
132 }
133
134 return 0;
135 }
136
peaks_update_rates_or_reset(pa_resampler * r)137 static void peaks_update_rates_or_reset(pa_resampler *r) {
138 struct peaks_data *peaks_data;
139 pa_assert(r);
140
141 peaks_data = r->impl.data;
142
143 peaks_data->i_counter = 0;
144 peaks_data->o_counter = 0;
145 }
146
pa_resampler_peaks_init(pa_resampler * r)147 int pa_resampler_peaks_init(pa_resampler*r) {
148 struct peaks_data *peaks_data;
149 pa_assert(r);
150 pa_assert(r->i_ss.rate >= r->o_ss.rate);
151 pa_assert(r->work_format == PA_SAMPLE_S16NE || r->work_format == PA_SAMPLE_FLOAT32NE);
152
153 peaks_data = pa_xnew0(struct peaks_data, 1);
154
155 r->impl.resample = peaks_resample;
156 r->impl.update_rates = peaks_update_rates_or_reset;
157 r->impl.reset = peaks_update_rates_or_reset;
158 r->impl.data = peaks_data;
159
160 return 0;
161 }
162