mixer.cpp
Go to the documentation of this file.00001
00002
00005 #include "stdafx.h"
00006 #include "mixer.h"
00007 #include "core/math_func.hpp"
00008
00009 struct MixerChannel {
00010 bool active;
00011
00012
00013 int8 *memory;
00014
00015
00016 uint32 pos;
00017 uint32 frac_pos;
00018 uint32 frac_speed;
00019 uint32 samples_left;
00020
00021
00022 int volume_left;
00023 int volume_right;
00024
00025 uint flags;
00026 };
00027
00028 static MixerChannel _channels[8];
00029 static uint32 _play_rate;
00030
00037 static const int MAX_VOLUME = 128 * 128;
00038
00039
00040 static void mix_int8_to_int16(MixerChannel *sc, int16 *buffer, uint samples)
00041 {
00042 int8 *b;
00043 uint32 frac_pos;
00044 uint32 frac_speed;
00045 int volume_left;
00046 int volume_right;
00047
00048 if (samples > sc->samples_left) samples = sc->samples_left;
00049 sc->samples_left -= samples;
00050 assert(samples > 0);
00051
00052 b = sc->memory + sc->pos;
00053 frac_pos = sc->frac_pos;
00054 frac_speed = sc->frac_speed;
00055 volume_left = sc->volume_left;
00056 volume_right = sc->volume_right;
00057
00058 if (frac_speed == 0x10000) {
00059
00060 do {
00061 buffer[0] = Clamp(buffer[0] + (*b * volume_left >> 8), -MAX_VOLUME, MAX_VOLUME);
00062 buffer[1] = Clamp(buffer[1] + (*b * volume_right >> 8), -MAX_VOLUME, MAX_VOLUME);
00063 b++;
00064 buffer += 2;
00065 } while (--samples > 0);
00066 } else {
00067 do {
00068 buffer[0] = Clamp(buffer[0] + (*b * volume_left >> 8), -MAX_VOLUME, MAX_VOLUME);
00069 buffer[1] = Clamp(buffer[1] + (*b * volume_right >> 8), -MAX_VOLUME, MAX_VOLUME);
00070 buffer += 2;
00071 frac_pos += frac_speed;
00072 b += frac_pos >> 16;
00073 frac_pos &= 0xffff;
00074 } while (--samples > 0);
00075 }
00076
00077 sc->frac_pos = frac_pos;
00078 sc->pos = b - sc->memory;
00079 }
00080
00081 static void MxCloseChannel(MixerChannel *mc)
00082 {
00083 if (mc->flags & MX_AUTOFREE) free(mc->memory);
00084 mc->active = false;
00085 mc->memory = NULL;
00086 }
00087
00088 void MxMixSamples(void *buffer, uint samples)
00089 {
00090 MixerChannel *mc;
00091
00092
00093 memset(buffer, 0, sizeof(int16) * 2 * samples);
00094
00095
00096 for (mc = _channels; mc != endof(_channels); mc++) {
00097 if (mc->active) {
00098 mix_int8_to_int16(mc, (int16*)buffer, samples);
00099 if (mc->samples_left == 0) MxCloseChannel(mc);
00100 }
00101 }
00102 }
00103
00104 MixerChannel *MxAllocateChannel()
00105 {
00106 MixerChannel *mc;
00107 for (mc = _channels; mc != endof(_channels); mc++)
00108 if (mc->memory == NULL) {
00109 mc->active = false;
00110 return mc;
00111 }
00112 return NULL;
00113 }
00114
00115 void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, size_t size, uint rate, uint flags)
00116 {
00117 mc->memory = mem;
00118 mc->flags = flags;
00119 mc->frac_pos = 0;
00120 mc->pos = 0;
00121
00122 mc->frac_speed = (rate << 16) / _play_rate;
00123
00124
00125 while (size & ~0xFFFF) {
00126 size >>= 1;
00127 rate = (rate >> 1) + 1;
00128 }
00129
00130 mc->samples_left = (uint)size * _play_rate / rate;
00131 }
00132
00133 void MxSetChannelVolume(MixerChannel *mc, uint left, uint right)
00134 {
00135 mc->volume_left = left;
00136 mc->volume_right = right;
00137 }
00138
00139
00140 void MxActivateChannel(MixerChannel *mc)
00141 {
00142 mc->active = true;
00143 }
00144
00145
00146 bool MxInitialize(uint rate)
00147 {
00148 _play_rate = rate;
00149 return true;
00150 }