Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
16 KB
Referenced Files
None
Subscribers
None
diff --git a/util/audio.cpp b/util/audio.cpp
index 69027f12..c4c2169c 100644
--- a/util/audio.cpp
+++ b/util/audio.cpp
@@ -1,350 +1,356 @@
#include <string.h>
#include "audio.h"
#include "debug.h"
namespace Util{
#ifdef USE_SDL1
AudioConverter::AudioConverter(Encoding inputEncoding, int inputChannels, int inputFrequency,
Encoding outputEncoding, int outputChannels, int outputFrequency){
SDL_BuildAudioCVT(&conversion, inputEncoding, inputChannels, inputFrequency,
outputEncoding, outputChannels, outputFrequency);
}
AudioConverter::~AudioConverter(){
}
int AudioConverter::convertedLength(int length){
return length;
}
int AudioConverter::convert(void * input, int length){
if (conversion.needed){
conversion.buf = (Uint8*) input;
conversion.len = length;
/* then convert to whatever the real output wants */
SDL_ConvertAudio(&conversion);
return conversion.len_cvt;
} else {
return length;
}
}
#else
AudioConverter::AudioConverter(Encoding inputEncoding, int inputChannels, int inputFrequency,
Encoding outputEncoding, int outputChannels, int outputFrequency):
buffer(NULL),
bufferSize(0){
input.bytes = inputEncoding;
input.channels = inputChannels;
input.frequency = inputFrequency;
output.bytes = outputEncoding;
output.channels = outputChannels;
output.frequency = outputFrequency;
sizeRatio = (double) byteSize(output) * output.frequency / ((double) byteSize(input) * input.frequency);
}
int AudioConverter::byteSize(const Format & what){
return encodingBytes(what.bytes) * what.channels;
}
/* how many bytes an encoding takes up */
int AudioConverter::encodingBytes(Encoding what){
switch (what){
case Unsigned8: return 1;
case Signed16: return 2;
case Unsigned16: return 2;
case Float32: return 4;
}
return 1;
}
int AudioConverter::convertedLength(int length){
// return length * sizeRatio;
int total = length * sizeRatio;
/* make sure we get an even number of samples */
if (total % byteSize(output) != 0){
total -= total % byteSize(output);
}
return total;
}
double CubicInterpolate(double y0, double y1,
double y2, double y3,
double mu){
double a0,a1,a2,a3,mu2;
mu2 = mu*mu;
a0 = y3 - y2 - y0 + y1;
a1 = y0 - y1 - a0;
a2 = y2 - y0;
a3 = y1;
return (a0*mu*mu2+a1*mu2+a2*mu+a3);
}
template <class Input, class Output>
Output clamp(double input){
Output top = (1 << (sizeof(Output) * 8 - 1)) - 1;
Output bottom = -(1 << (sizeof(Output) * 8 - 1));
if (input > top){
return top;
}
if (input < bottom){
return bottom;
}
return input;
}
template <>
signed short clamp<unsigned char>(double input){
return ((input - 127) / 255) * (1 << (sizeof(signed short) * 8 - 1));
}
template <>
unsigned char clamp<unsigned char>(double input){
if (input > 255){
input = 255;
}
if (input < 0){
input = 0;
}
return input;
}
template <>
float clamp<float>(double input){
+ if (input > 1){
+ input = 1;
+ }
+ if (input < -1){
+ input = -1;
+ }
return input;
}
template <>
unsigned short clamp<signed short>(double input){
return (int) clamp<signed short, signed short>(input) + (int) (1 << (sizeof(signed short) * 8 - 1));
}
template <>
float clamp<short unsigned int>(double input){
double out = input / (1 << (sizeof(unsigned short) * 8));
if (out > 1){
return 1;
}
if (out < -1){
return -1;
}
return out;
}
template <>
float clamp<unsigned char>(double input){
double out = input / (1 << (sizeof(unsigned char) * 8));
if (out > 1){
return 1;
}
if (out < -1){
return -1;
}
return out;
}
template <>
unsigned char clamp<signed short>(double input){
double out = input / (1 << (sizeof(signed short) * 8 - 1));
if (out > 1){
return 1;
}
if (out < -1){
return -1;
}
/* -1,1 -> 0,255 */
return (unsigned char)((out + 1) * 128);
}
template <>
float clamp<signed short>(double input){
double out = input / (1 << (sizeof(signed short) * 8 - 1));
if (out > 1){
return 1;
}
if (out < -1){
return -1;
}
return out;
}
template <class SizeInput, class SizeOutput>
void doConvertRate(SizeInput * input, int inputSamples, int inputChannels, SizeOutput * buffer, int outputSamples, int outputChannels, double ratio){
for (int sample = 0; sample < outputSamples; sample += 1){
double inputSample = sample / ratio;
for (int channel = 0; channel < outputChannels; channel += 1){
int inputChannel = inputChannels > channel ? channel : inputChannels - 1;
int sample0 = ((int) inputSample - 1) * inputChannels + inputChannel;
int sample1 = ((int) inputSample + 0) * inputChannels + inputChannel;
int sample2 = ((int) inputSample + 1) * inputChannels + inputChannel;
int sample3 = ((int) inputSample + 2) * inputChannels + inputChannel;
if (sample0 < 0){
sample0 = sample1;
}
if (sample2 >= inputSamples * inputChannels){
sample2 = sample1;
}
if (sample3 >= inputSamples * inputChannels){
sample3 = sample2;
}
buffer[sample * outputChannels + channel] = clamp<SizeInput, SizeOutput>(CubicInterpolate(input[sample0], input[sample1], input[sample2], input[sample3], inputSample - (int) inputSample));
// Global::debug(0) << "Input[" << sample << "] " << channel << ": " << input[sample1] << " Output: " << buffer[sample * 2 + channel] << std::endl;
}
}
}
template <class Input, class Output>
void doConvert3(void * input, int inputLength, int inputChannels,
void * output, int outputLength, int outputChannels,
double ratio){
doConvertRate<Input, Output>((Input*) input, inputLength / sizeof(Input) / inputChannels, inputChannels,
(Output*) output, outputLength / sizeof(Output) / outputChannels, outputChannels,
ratio);
}
template <class Input>
void doConvert2(void * input, int inputLength, int inputChannels,
Encoding outputType, void * output, int outputLength, int outputChannels,
double ratio){
switch (outputType){
case Unsigned8: doConvert3<Input, unsigned char>(input, inputLength, inputChannels, output, outputLength, outputChannels, ratio); break;
case Signed16: doConvert3<Input, signed short>(input, inputLength, inputChannels, output, outputLength, outputChannels, ratio); break;
case Unsigned16: doConvert3<Input, unsigned short>(input, inputLength, inputChannels, output, outputLength, outputChannels, ratio); break;
case Float32: doConvert3<Input, float>(input, inputLength, inputChannels, output, outputLength, outputChannels, ratio); break;
}
}
void doConvert1(Encoding inputType, void * input, int inputLength, int inputChannels,
Encoding outputType, void * output, int outputLength, int outputChannels, double ratio){
switch (inputType){
case Unsigned8: doConvert2<unsigned char>(input, inputLength, inputChannels, outputType, output, outputLength, outputChannels, ratio); break;
case Signed16: doConvert2<signed short>(input, inputLength, inputChannels, outputType, output, outputLength, outputChannels, ratio); break;
case Unsigned16: doConvert2<unsigned short>(input, inputLength, inputChannels, outputType, output, outputLength, outputChannels, ratio); break;
case Float32: doConvert2<float>(input, inputLength, inputChannels, outputType, output, outputLength, outputChannels, ratio); break;
}
}
int AudioConverter::convert(void * input, int length){
/* no conversion needed */
if (this->input == this->output){
return length;
}
int total = convertedLength(length);
/*
if (total % byteSize(output) != 0){
total -= total % byteSize(output);
}
*/
/* cache the buffer for future use */
if (total > bufferSize){
delete[] buffer;
bufferSize = total;
buffer = new char[bufferSize];
}
double frequencyRatio = (double) output.frequency / (double) this->input.frequency;
doConvert1(this->input.bytes, input, length, this->input.channels, output.bytes, buffer, total, output.channels, frequencyRatio);
/*
switch (this->input.bytes){
case Unsigned8: {
switch (this->output.bytes){
case Unsigned8: doConvertRate<unsigned char, unsigned char>(
(unsigned char*) input, length / sizeof(unsigned char) / this->input.channels, this->input.channels,
(unsigned char*) buffer, total / sizeof(unsigned char) / output.channels, output.channels,
frequencyRatio); break;
case Signed16: doConvertRate<unsigned char, unsigned char>(
(unsigned char*) input, length / sizeof(unsigned char) / this->input.channels, this->input.channels,
(unsigned char*) buffer, total / sizeof(unsigned char) / output.channels, output.channels,
frequencyRatio); break;
}
}
case Signed16: {
switch (this->output.bytes){
case Signed16: doConvertRate<signed short, signed short>(
(signed short*) input, length / sizeof(signed short) / this->input.channels, this->input.channels,
(signed short*) buffer, total / sizeof(signed short) / output.channels, output.channels,
frequencyRatio); break;
case Unsigned8: doConvertRate<signed short, unsigned char>(
(signed short*) input, length / sizeof(signed short) / this->input.channels, this->input.channels,
(unsigned char*) buffer, total / sizeof(unsigned char) / output.channels, output.channels,
frequencyRatio); break;
case Unsigned16: doConvertRate<signed short, unsigned short>(
(signed short*) input, length / sizeof(signed short) / this->input.channels, this->input.channels,
(unsigned short*) buffer, total / sizeof(unsigned short) / output.channels, output.channels,
frequencyRatio); break;
case Float32: doConvertRate<signed short, float>(
(signed short*) input, length / sizeof(signed short) / this->input.channels, this->input.channels,
(float*) buffer, total / sizeof(float) / output.channels, output.channels,
frequencyRatio); break;
}
break;
}
case Float32: {
switch (this->output.bytes){
case Float32: doConvertRate<float, float>(
(float*) input, length / sizeof(float) / this->input.channels, this->input.channels,
(float*) buffer, total / sizeof(float) / output.channels, output.channels,
frequencyRatio); break;
default: break;
}
break;
}
default: break;
}
*/
/*
if (this->input.bytes == output.bytes){
switch (this->input.bytes){
case Signed16: doConvertRate<signed short, signed short>((signed short*) input, length / sizeof(signed short) / this->input.channels, this->input.channels,
(signed short*) buffer, total / sizeof(signed short) / output.channels, output.channels,
frequencyRatio); break;
case Float32: doConvertRate<float, float>((float*) input, length / sizeof(float) / this->input.channels, this->input.channels,
(float*) buffer, total / sizeof(float) / output.channels, output.channels, frequencyRatio); break;
}
}
*/
memcpy(input, buffer, total);
return total;
}
AudioConverter::~AudioConverter(){
delete[] buffer;
}
bool AudioConverter::Format::operator==(const AudioConverter::Format & him) const {
return this->bytes == him.bytes &&
this->channels == him.channels &&
this->frequency == him.frequency;
}
#endif
}
diff --git a/util/sdl/mixer/convert.cpp b/util/sdl/mixer/convert.cpp
index 7ede13ae..857adb97 100644
--- a/util/sdl/mixer/convert.cpp
+++ b/util/sdl/mixer/convert.cpp
@@ -1,88 +1,70 @@
#include "convert.h"
#include "SDL_mixer.h"
#include "util/audio.h"
Util::Encoding encoding(int format){
switch (format){
case AUDIO_U8: return Util::Unsigned8;
case AUDIO_S16: return Util::Signed16;
case AUDIO_U16: return Util::Unsigned16;
#if SDL_VERSION_ATLEAST(1, 3, 0)
- case AUDIO_F32: return Util::Float32;
+ case AUDIO_F32LSB:
+ case AUDIO_F32MSB: return Util::Float32;
#endif
}
return Util::Signed16;
}
/* use SDL to convert between formats */
-void convertFormat(SDL_AudioSpec * wav, int format, Mix_Chunk * chunk){
+int convertFormat(SDL_AudioSpec * wav, int format, Mix_Chunk * chunk){
SDL_AudioCVT wavecvt;
int samplesize;
if (SDL_BuildAudioCVT(&wavecvt,
wav->format, wav->channels, wav->freq,
format, wav->channels, wav->freq) < 0){
SDL_FreeWAV(chunk->abuf);
free(chunk);
+ return 1;
}
samplesize = ((wav->format & 0xFF)/8)*wav->channels;
wavecvt.len = chunk->alen & ~(samplesize-1);
wavecvt.buf = (Uint8 *)malloc(wavecvt.len*wavecvt.len_mult);
if ( wavecvt.buf == NULL ) {
SDL_SetError("Out of memory");
SDL_FreeWAV(chunk->abuf);
free(chunk);
+ return 1;
}
memcpy(wavecvt.buf, chunk->abuf, chunk->alen);
SDL_FreeWAV(chunk->abuf);
if ( SDL_ConvertAudio(&wavecvt) < 0 ) {
free(wavecvt.buf);
free(chunk);
+ return 1;
}
chunk->abuf = wavecvt.buf;
chunk->alen = wavecvt.len_cvt;
+ return 0;
}
extern "C" void convertAudio(SDL_AudioSpec * wav, SDL_AudioSpec * mixer, Mix_Chunk *chunk){
// printf("Convert format %d, channels %d, frequency %d to format %d, channels %d, frequency %d\n", wav->format, wav->channels, wav->freq, mixer->format, mixer->channels, mixer->freq);
- convertFormat(wav, mixer->format, chunk);
+ if (convertFormat(wav, mixer->format, chunk)){
+ printf("Could not convert format!\n");
+ return;
+ }
+
+ // printf("Mixer format %d to encoding %d\n", mixer->format, encoding(mixer->format));
/* format is now what the mixer wants */
Util::AudioConverter convert(encoding(mixer->format), wav->channels, wav->freq,
encoding(mixer->format), mixer->channels, mixer->freq);
int size = convert.convertedLength(chunk->alen);
unsigned char * data = (unsigned char *) malloc(size > chunk->alen ? size : chunk->alen);
memcpy(data, chunk->abuf, chunk->alen);
convert.convert(data, chunk->alen);
SDL_FreeWAV(chunk->abuf);
chunk->abuf = data;
chunk->alen = size;
-
- /*
- SDL_AudioCVT wavecvt;
- int samplesize;
- if ( SDL_BuildAudioCVT(&wavecvt,
- wav->format, wav->channels, wav->freq,
- mixer->format, mixer->channels, mixer->freq) < 0 ) {
- SDL_FreeWAV(chunk->abuf);
- free(chunk);
- }
- samplesize = ((wav->format & 0xFF)/8)*wav->channels;
- wavecvt.len = chunk->alen & ~(samplesize-1);
- wavecvt.buf = (Uint8 *)malloc(wavecvt.len*wavecvt.len_mult);
- if ( wavecvt.buf == NULL ) {
- SDL_SetError("Out of memory");
- SDL_FreeWAV(chunk->abuf);
- free(chunk);
- }
- memcpy(wavecvt.buf, chunk->abuf, chunk->alen);
- SDL_FreeWAV(chunk->abuf);
-
- if ( SDL_ConvertAudio(&wavecvt) < 0 ) {
- free(wavecvt.buf);
- free(chunk);
- }
- chunk->abuf = wavecvt.buf;
- chunk->alen = wavecvt.len_cvt;
- */
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 10:04 AM (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68268
Default Alt Text
(16 KB)

Event Timeline