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