libsidplayfp 2.3.1
mixer.h
1/*
2 * This file is part of libsidplayfp, a SID player engine.
3 *
4 * Copyright 2011-2015 Leandro Nini <drfiemost@users.sourceforge.net>
5 * Copyright 2007-2010 Antti Lankila
6 * Copyright (C) 2000 Simon White
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; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23
24#ifndef MIXER_H
25#define MIXER_H
26
27#include "sidcxx11.h"
28
29#include <stdint.h>
30#include <cstdlib>
31
32#include <vector>
33
34namespace libsidplayfp
35{
36
37class sidemu;
38
42class Mixer
43{
44public:
46 static const unsigned int MAX_SIDS = 3;
47
48 static const int_least32_t SCALE_FACTOR = 1 << 16;
49#ifdef HAVE_CXX11
50 static constexpr double SQRT_0_5 = 0.70710678118654746;
51#else
52# define SQRT_0_5 0.70710678118654746
53#endif
54 static const int_least32_t C1 = static_cast<int_least32_t>(1.0 / (1.0 + SQRT_0_5) * SCALE_FACTOR);
55 static const int_least32_t C2 = static_cast<int_least32_t>(SQRT_0_5 / (1.0 + SQRT_0_5) * SCALE_FACTOR);
56
57private:
58 typedef int_least32_t (Mixer::*mixer_func_t)() const;
59
60public:
62 static const int_least32_t VOLUME_MAX = 1024;
63
64private:
65 std::vector<sidemu*> m_chips;
66 std::vector<short*> m_buffers;
67
68 std::vector<int_least32_t> m_iSamples;
69 std::vector<int_least32_t> m_volume;
70
71 std::vector<mixer_func_t> m_mix;
72
73 int oldRandomValue;
74 int m_fastForwardFactor;
75
76 // Mixer settings
77 short *m_sampleBuffer;
78 uint_least32_t m_sampleCount;
79 uint_least32_t m_sampleIndex;
80
81 bool m_stereo;
82
83private:
84 void updateParams();
85
86 int triangularDithering()
87 {
88 const int prevValue = oldRandomValue;
89 oldRandomValue = rand() & (VOLUME_MAX-1);
90 return oldRandomValue - prevValue;
91 }
92
93 /*
94 * Channel matrix
95 *
96 * C1
97 * L 1.0
98 * R 1.0
99 *
100 * C1 C2
101 * L 1.0 0.0
102 * R 0.0 1.0
103 *
104 * C1 C2 C3
105 * L 1/1.707 0.707/1.707 0.0
106 * R 0.0 0.707/1.707 1/1.707
107 *
108 * FIXME
109 * it seems that scaling down the summed signals is not the correct way of mixing, see:
110 * http://dsp.stackexchange.com/questions/3581/algorithms-to-mix-audio-signals-without-clipping
111 * maybe we should consider some form of soft/hard clipping instead to avoid possible overflows
112 */
113
114 // Mono mixing
115 template <int Chips>
116 int_least32_t mono() const
117 {
118 int_least32_t res = 0;
119 for (int i = 0; i < Chips; i++)
120 res += m_iSamples[i];
121 return res / Chips;
122 }
123
124 // Stereo mixing
125 int_least32_t stereo_OneChip() const { return m_iSamples[0]; }
126
127 int_least32_t stereo_ch1_TwoChips() const { return m_iSamples[0]; }
128 int_least32_t stereo_ch2_TwoChips() const { return m_iSamples[1]; }
129
130 int_least32_t stereo_ch1_ThreeChips() const { return (C1*m_iSamples[0] + C2*m_iSamples[1]) / SCALE_FACTOR; }
131 int_least32_t stereo_ch2_ThreeChips() const { return (C2*m_iSamples[1] + C1*m_iSamples[2]) / SCALE_FACTOR; }
132
133public:
138 oldRandomValue(0),
139 m_fastForwardFactor(1),
140 m_sampleCount(0),
141 m_stereo(false)
142 {
143 m_mix.push_back(&Mixer::mono<1>);
144 }
145
149 void doMix();
150
154 void clockChips();
155
159 void resetBufs();
160
167 void begin(short *buffer, uint_least32_t count);
168
172 void clearSids();
173
179 void addSid(sidemu *chip);
180
187 sidemu* getSid(unsigned int i) const { return (i < m_chips.size()) ? m_chips[i] : nullptr; }
188
195 bool setFastForward(int ff);
196
203 void setVolume(int_least32_t left, int_least32_t right);
204
210 void setStereo(bool stereo);
211
215 bool notFinished() const { return m_sampleIndex != m_sampleCount; }
216
220 uint_least32_t samplesGenerated() const { return m_sampleIndex; }
221};
222
223}
224
225#endif // MIXER_H
Definition: mixer.h:43
void addSid(sidemu *chip)
Definition: mixer.cpp:164
static const int_least32_t VOLUME_MAX
Maximum allowed volume, must be a power of 2.
Definition: mixer.h:62
void resetBufs()
Definition: mixer.cpp:69
Mixer()
Definition: mixer.h:137
void clearSids()
Definition: mixer.cpp:158
bool notFinished() const
Definition: mixer.h:215
void clockChips()
Definition: mixer.cpp:64
void setStereo(bool stereo)
Definition: mixer.cpp:178
void setVolume(int_least32_t left, int_least32_t right)
Definition: mixer.cpp:199
sidemu * getSid(unsigned int i) const
Definition: mixer.h:187
uint_least32_t samplesGenerated() const
Definition: mixer.h:220
void doMix()
Definition: mixer.cpp:74
void begin(short *buffer, uint_least32_t count)
Definition: mixer.cpp:132
bool setFastForward(int ff)
Definition: mixer.cpp:190
static const unsigned int MAX_SIDS
Maximum number of supported SIDs.
Definition: mixer.h:46
Definition: sidemu.h:47