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