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