1 // Copyright (C) 2000-2005 Open Source Telecom Corporation.
2 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
3 // Copyright (C) 2015 Cherokees of Idaho.
4 //
5 // This file is part of GNU ccAudio2.
6 //
7 // GNU ccAudio2 is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Lesser General Public License as published
9 // by the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // GNU ccAuydio2 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 Lesser General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with GNU ccAudio2. If not, see <http://www.gnu.org/licenses/>.
19
20 #include <ucommon/ucommon.h>
21 #include <ccaudio2-config.h>
22 #include <ucommon/export.h>
23 #include <ccaudio2.h>
24
25 namespace ucommon {
26
AudioResample(Rate div,Rate mul)27 AudioResample::AudioResample(Rate div, Rate mul)
28 {
29 bool common = true;
30 while(common) {
31 common = false;
32
33 while(!(mul & 0x01) && !(div & 0x01)) {
34 mul = (Rate)(mul >> 1);
35 div = (Rate)(div >> 1);
36 common = true;
37 }
38
39 while(!(mul % 3) && !(div % 3)) {
40 mul = (Rate)(mul / 3);
41 div = (Rate)(div / 3);
42 common = true;
43 }
44
45 while(!(mul % 5) && !(div %5)) {
46 mul = (Rate)(mul / 5);
47 div = (Rate)(div / 5);
48 common = true;
49 }
50 }
51
52
53 mfact = (unsigned)mul;
54 dfact = (unsigned)div;
55
56 max = mfact;
57 if(dfact > mfact)
58 max = dfact;
59
60 ++max;
61 buffer = new Sample[max];
62 ppos = gpos = 0;
63 memset(buffer, 0, max * 2);
64 last = 0;
65 }
66
~AudioResample()67 AudioResample::~AudioResample()
68 {
69 delete[] buffer;
70 }
71
estimate(size_t count)72 size_t AudioResample::estimate(size_t count)
73 {
74 count *= mfact;
75 count += (mfact - 1);
76 return (count / dfact) + 1;
77 }
78
process(Linear from,Linear dest,size_t count)79 size_t AudioResample::process(Linear from, Linear dest, size_t count)
80 {
81 size_t saved = 0;
82 Sample diff, current;
83 unsigned pos;
84 unsigned dpos;
85
86 while(count--) {
87 current = *(from++);
88 diff = (current - last) / mfact;
89 pos = mfact;
90 while(pos--) {
91 last += diff;
92 buffer[ppos++] = current;
93 if(ppos >= max)
94 ppos = 0;
95
96 if(gpos < ppos)
97 dpos = ppos - gpos;
98 else
99 dpos = max - (gpos - ppos);
100 if(dpos >= dfact) {
101 *(dest++) = buffer[gpos];
102 ++saved;
103 gpos += dfact;
104 if(gpos >= max)
105 gpos = gpos - max;
106 }
107 }
108 last = current;
109 }
110 return saved;
111 }
112
113 } // namespace ucommon
114