00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #include "AudioChannel.h"
00022 #include "AudioSample.h"
00023
00024 namespace Pentagram {
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #define RANGE_REDUX(x) (((x) * 27) >> 5)
00036
00037 AudioChannel::AudioChannel(uint32 sample_rate_, bool stereo_) :
00038 playdata(0), playdata_size(0), decompressor_size(0), frame_size(0),
00039 sample_rate(sample_rate_), stereo(stereo_),
00040 loop(0), sample(0),
00041 frame_evenodd(0), frame0_size(0), frame1_size(0), position(0), paused(false),
00042 fp_pos(0), fp_speed(0)
00043 {
00044 }
00045
00046 AudioChannel::~AudioChannel(void)
00047 {
00048 }
00049
00050 void AudioChannel::playSample(AudioSample *sample_, int loop_, int priority_, bool paused_, uint32 pitch_shift_, int lvol_, int rvol_)
00051 {
00052 sample = sample_;
00053 loop = loop_;
00054 priority = priority_;
00055 lvol = lvol_;
00056 rvol = rvol_;
00057 paused = paused_;
00058 pitch_shift = pitch_shift_;
00059
00060 if (!sample) return;
00061
00062
00063 decompressor_size = sample->getDecompressorDataSize();
00064 frame_size = sample->getFrameSize();
00065
00066 if ((decompressor_size + frame_size*2) > playdata_size)
00067 {
00068 delete [] playdata;
00069 playdata_size = decompressor_size + frame_size*2;
00070 playdata = new uint8[playdata_size];
00071 }
00072
00073
00074 sample->initDecompressor(playdata);
00075
00076
00077 frame_evenodd = 0;
00078 position = 0;
00079 fp_pos = 0;
00080 fp_speed = (pitch_shift*sample->getRate())/sample_rate;
00081
00082
00083 frame0_size = sample->decompressFrame(playdata, playdata+decompressor_size);
00084
00085
00086 DecompressNextFrame();
00087
00088
00089 if (sample->getBits()==8 && !sample->isStereo())
00090 {
00091 uint8 *src = playdata+decompressor_size;
00092 int a = *(src+0); a = (a|(a << 8))-32768;
00093 int b = *(src+1); b = (a|(b << 8))-32768;
00094 int c = *(src+2); c = (a|(c << 8))-32768;
00095
00096 interp_l.init(RANGE_REDUX(a),RANGE_REDUX(b),RANGE_REDUX(c));
00097 }
00098
00099 }
00100
00101 void AudioChannel::resampleAndMix(sint16 *stream, uint32 bytes)
00102 {
00103 if (!sample || paused) return;
00104
00105
00106 fp_speed = (pitch_shift*sample->getRate())/sample_rate;
00107
00108
00109 do
00110 {
00111
00112 if (sample->getBits()==8) {
00113
00114 if (!sample->isStereo() && stereo)
00115 resampleFrameM8toS(stream,bytes);
00116 if (!sample->isStereo() && !stereo)
00117 resampleFrameM8toM(stream,bytes);
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 if (bytes || (position == frame0_size)) {
00152
00153
00154 if (!frame1_size) {
00155 sample = 0;
00156 return;
00157 }
00158
00159
00160 frame_evenodd = 1-frame_evenodd;
00161
00162
00163 frame0_size = frame1_size;
00164 position = 0;
00165
00166 DecompressNextFrame();
00167 }
00168
00169 } while (bytes!=0);
00170 }
00171
00172
00173 void AudioChannel::DecompressNextFrame()
00174 {
00175
00176 uint8 *src2 = playdata + decompressor_size + (frame_size*(1-frame_evenodd));
00177 frame1_size = sample->decompressFrame(playdata, src2);
00178
00179
00180 if (!frame1_size && loop) {
00181 if (loop != -1) loop--;
00182 sample->rewind(playdata);
00183 frame1_size = sample->decompressFrame(playdata, src2);
00184 }
00185 }
00186
00187
00188 void AudioChannel::resampleFrameM8toS(sint16 *&stream, uint32 &bytes)
00189 {
00190 uint8 *src = playdata + decompressor_size + (frame_size*frame_evenodd);
00191 uint8 *src2 = playdata + decompressor_size + (frame_size*(1-frame_evenodd));
00192
00193 uint8 *src_end = src + frame0_size;
00194 uint8 *src2_end = src2 + frame1_size;
00195
00196 src += position;
00197
00198 int result;
00199
00200 do {
00201
00202 if (fp_pos >= 0x10000)
00203 {
00204 if (src+2 < src_end) {
00205 int c = *(src+2);
00206 c = (c|(c << 8))-32768;
00207 interp_l.feedData(c);
00208 } else if (src2 < src2_end) {
00209 int c = *(src2);
00210 c = (c|(c << 8))-32768;
00211 interp_l.feedData(c);
00212 src2++;
00213 } else {
00214 interp_l.feedData();
00215 }
00216 src++;
00217 fp_pos -= 0x10000;
00218 }
00219
00220 if (fp_pos < 0x10000) do {
00221
00222 result = interp_l.interpolate(fp_pos);
00223
00224 int lresult = *(stream+0) + (result*lvol)/256;
00225 int rresult = *(stream+1) + (result*rvol)/256;
00226
00227
00228
00229 if (lresult < -32768) lresult = -32768;
00230 else if (lresult > 32767) lresult = 32767;
00231
00232 if (rresult < -32768) rresult = -32768;
00233 else if (rresult > 32767) rresult = 32767;
00234
00235 *stream++ = lresult;
00236 *stream++ = rresult;
00237 bytes -= 4;
00238 fp_pos += fp_speed;
00239
00240 } while (fp_pos < 0x10000 && bytes!=0);
00241
00242 } while (bytes!=0 && src != src_end);
00243
00244 position = frame0_size - (src_end - src);
00245 }
00246
00247
00248 void AudioChannel::resampleFrameM8toM(sint16 *&stream, uint32 &bytes)
00249 {
00250 uint8 *src = playdata + decompressor_size + (frame_size*frame_evenodd);
00251 uint8 *src2 = playdata + decompressor_size + (frame_size*(1-frame_evenodd));
00252
00253 uint8 *src_end = src + frame0_size;
00254 uint8 *src2_end = src2 + frame1_size;
00255
00256 src += position;
00257
00258 int result;
00259 int volume = (rvol + lvol)/2;
00260
00261 do {
00262
00263 if (fp_pos >= 0x10000)
00264 {
00265 if (src+2 < src_end) {
00266 int c = *(src+2);
00267 c = (c|(c << 8))-32768;
00268 interp_l.feedData(c);
00269 } else if (src2 < src2_end) {
00270 int c = *(src2);
00271 c = (c|(c << 8))-32768;
00272 interp_l.feedData(c);
00273 src2++;
00274 } else {
00275 interp_l.feedData();
00276 }
00277 src++;
00278 fp_pos -= 0x10000;
00279 }
00280
00281 if (fp_pos < 0x10000) do {
00282
00283 result = (interp_l.interpolate(fp_pos)*volume)/256;
00284
00285 result += *stream;
00286
00287
00288
00289 if (result < -32768) result = -32768;
00290 else if (result > 32767) result = 32767;
00291
00292 *stream++ = result;
00293 bytes -= 2;
00294 fp_pos += fp_speed;
00295
00296 } while (fp_pos < 0x10000 && bytes!=0);
00297
00298 } while (bytes!=0 && src != src_end);
00299
00300 position = frame0_size - (src_end - src);
00301 }
00302
00303 };
00304