1 /***************************************************************************
2 mixer.cpp - Sids Mixer Routines
3 -------------------
4 begin : Sun Jul 9 2000
5 copyright : (C) 2000 by Simon White
6 email : s_a_white@email.com
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17 /***************************************************************************
18 * $Log: mixer.cpp,v $
19 * Revision 1.10 2002/01/29 21:50:33 s_a_white
20 * Auto switching to a better emulation mode. m_tuneInfo reloaded after a
21 * config. Initial code added to support more than two sids.
22 *
23 * Revision 1.9 2001/12/13 08:28:08 s_a_white
24 * Added namespace support to fix problems with xsidplay.
25 *
26 * Revision 1.8 2001/11/16 19:25:33 s_a_white
27 * Removed m_context as where getting mixed with parent class.
28 *
29 * Revision 1.7 2001/10/02 18:29:32 s_a_white
30 * Corrected fixed point maths overflow caused by fastforwarding.
31 *
32 * Revision 1.6 2001/09/17 19:02:38 s_a_white
33 * Now uses fixed point maths for sample output and rtc.
34 *
35 * Revision 1.5 2001/07/25 17:02:37 s_a_white
36 * Support for new configuration interface.
37 *
38 * Revision 1.4 2001/07/14 12:47:39 s_a_white
39 * Mixer routines simplified. Added new and more efficient method of
40 * determining when an output samples is required.
41 *
42 * Revision 1.3 2001/03/01 23:46:37 s_a_white
43 * Support for sample mode to be selected at runtime.
44 *
45 * Revision 1.2 2000/12/12 22:50:15 s_a_white
46 * Bug Fix #122033.
47 *
48 ***************************************************************************/
49
50 #include "player.h"
51 #include "sidendian.h"
52
53 const int_least32_t VOLUME_MAX = 255;
54
55 SIDPLAY2_NAMESPACE_START
56
mixerReset(void)57 void Player::mixerReset (void)
58 { // Fixed point 16.16
59 m_sampleClock = m_samplePeriod & 0x0FFFF;
60 // Schedule next sample event
61 (context ()).schedule (&mixerEvent,
62 m_samplePeriod >> 24);
63 }
64
mixer(void)65 void Player::mixer (void)
66 { // Fixed point 16.16
67 event_clock_t cycles;
68 char *buf = m_sampleBuffer + m_sampleIndex;
69 m_sampleClock += m_samplePeriod;
70 cycles = m_sampleClock >> 16;
71 m_sampleClock &= 0x0FFFF;
72 m_sampleIndex += (this->*output) (buf);
73
74 // Schedule next sample event
75 (context ()).schedule (&mixerEvent, cycles);
76
77 // Filled buffer
78 if (m_sampleIndex >= m_sampleCount)
79 m_running = false;
80 }
81
82
83 //-------------------------------------------------------------------------
84 // Generic sound output generation routines
85 //-------------------------------------------------------------------------
86 inline
monoOutGenericLeftIn(uint_least8_t bits)87 int_least32_t Player::monoOutGenericLeftIn (uint_least8_t bits)
88 {
89 return sid[0]->output (bits) * m_leftVolume / VOLUME_MAX;
90 }
91
92 inline
monoOutGenericStereoIn(uint_least8_t bits)93 int_least32_t Player::monoOutGenericStereoIn (uint_least8_t bits)
94 {
95 // Convert to mono
96 return ((sid[0]->output (bits) * m_leftVolume) +
97 (sid[1]->output (bits) * m_rightVolume)) / (VOLUME_MAX * 2);
98 }
99
100 inline
monoOutGenericRightIn(uint_least8_t bits)101 int_least32_t Player::monoOutGenericRightIn (uint_least8_t bits)
102 {
103 return sid[1]->output (bits) * m_rightVolume / VOLUME_MAX;
104 }
105
106
107 //-------------------------------------------------------------------------
108 // 8 bit sound output generation routines
109 //-------------------------------------------------------------------------
monoOut8MonoIn(char * buffer)110 uint_least32_t Player::monoOut8MonoIn (char *buffer)
111 {
112 *buffer = (char) monoOutGenericLeftIn (8) ^ '\x80';
113 return sizeof (char);
114 }
115
monoOut8StereoIn(char * buffer)116 uint_least32_t Player::monoOut8StereoIn (char *buffer)
117 {
118 *buffer = (char) monoOutGenericStereoIn (8) ^ '\x80';
119 return sizeof (char);
120 }
121
monoOut8StereoRIn(char * buffer)122 uint_least32_t Player::monoOut8StereoRIn (char *buffer)
123 {
124 *buffer = (char) monoOutGenericRightIn (8) ^ '\x80';
125 return sizeof (char);
126 }
127
stereoOut8MonoIn(char * buffer)128 uint_least32_t Player::stereoOut8MonoIn (char *buffer)
129 {
130 char sample = (char) monoOutGenericLeftIn (8) ^ '\x80';
131 buffer[0] = sample;
132 buffer[1] = sample;
133 return (2 * sizeof (char));
134 }
135
stereoOut8StereoIn(char * buffer)136 uint_least32_t Player::stereoOut8StereoIn (char *buffer)
137 {
138 buffer[0] = (char) monoOutGenericLeftIn (8) ^ '\x80';
139 buffer[1] = (char) monoOutGenericRightIn (8) ^ '\x80';
140 return (2 * sizeof (char));
141 }
142
143 //-------------------------------------------------------------------------
144 // 16 bit sound output generation routines
145 //-------------------------------------------------------------------------
monoOut16MonoIn(char * buffer)146 uint_least32_t Player::monoOut16MonoIn (char *buffer)
147 {
148 endian_16 (buffer, (uint_least16_t) monoOutGenericLeftIn (16));
149 return sizeof (uint_least16_t);
150 }
151
monoOut16StereoIn(char * buffer)152 uint_least32_t Player::monoOut16StereoIn (char *buffer)
153 {
154 endian_16 (buffer, (uint_least16_t) monoOutGenericStereoIn (16));
155 return sizeof (uint_least16_t);
156 }
157
monoOut16StereoRIn(char * buffer)158 uint_least32_t Player::monoOut16StereoRIn (char *buffer)
159 {
160 endian_16 (buffer, (uint_least16_t) monoOutGenericRightIn (16));
161 return sizeof (uint_least16_t);
162 }
163
stereoOut16MonoIn(char * buffer)164 uint_least32_t Player::stereoOut16MonoIn (char *buffer)
165 {
166 uint_least16_t sample = (uint_least16_t) monoOutGenericLeftIn (16);
167 endian_16 (buffer, sample);
168 endian_16 (buffer + sizeof(uint_least16_t), sample);
169 return (2 * sizeof (uint_least16_t));
170 }
171
stereoOut16StereoIn(char * buffer)172 uint_least32_t Player::stereoOut16StereoIn (char *buffer)
173 {
174 endian_16 (buffer, (uint_least16_t) monoOutGenericLeftIn (16));
175 endian_16 (buffer + sizeof(uint_least16_t),
176 (uint_least16_t) monoOutGenericRightIn (16));
177 return (2 * sizeof (uint_least16_t));
178 }
179
180 SIDPLAY2_NAMESPACE_STOP
181