⛏️ index : haiku.git

/*
 * Copyright 2012 Jérôme Leveque
 * Copyright 2012 Jérôme Duval
 * Copyright 2003 Marcus Overhagen
 * Distributed under the terms of the MIT License.
 */


#include "Resampler.h"
#include "MultiAudioUtility.h"
#include "debug.h"


/*!	A simple resampling class for the multi_audio add-ons.
	You pick the conversion function on object creation,
	and then call the Resample() function, specifying data pointer,
	offset (in bytes) to the next sample, and count of samples.
*/


Resampler::Resampler(uint32 sourceFormat, uint32 destFormat)
	:
	fFunc(&Resampler::_Void)
{
	PRINT(("Resampler() in 0x%x, out 0x%x\n", (unsigned int)sourceFormat,
		(unsigned int)destFormat));

	switch (sourceFormat) {
		case media_raw_audio_format::B_AUDIO_FLOAT:
			switch (destFormat) {
				case media_raw_audio_format::B_AUDIO_FLOAT:
					fFunc = &Resampler::_CopyFloat2Float;
					break;
				case media_raw_audio_format::B_AUDIO_DOUBLE:
					fFunc = &Resampler::_CopyFloat2Double;
					break;
				case media_raw_audio_format::B_AUDIO_INT:
					fFunc = &Resampler::_CopyFloat2Int;
					break;
				case media_raw_audio_format::B_AUDIO_SHORT:
					fFunc = &Resampler::_CopyFloat2Short;
					break;
				case media_raw_audio_format::B_AUDIO_UCHAR:
					fFunc = &Resampler::_CopyFloat2UChar;
					break;
				case media_raw_audio_format::B_AUDIO_CHAR:
					fFunc = &Resampler::_CopyFloat2Char;
					break;
			}
			break;

		case media_raw_audio_format::B_AUDIO_DOUBLE:
			switch (destFormat) {
				case media_raw_audio_format::B_AUDIO_FLOAT:
					fFunc = &Resampler::_CopyDouble2Float;
					break;
				case media_raw_audio_format::B_AUDIO_DOUBLE:
					fFunc = &Resampler::_CopyDouble2Double;
					break;
				case media_raw_audio_format::B_AUDIO_INT:
					fFunc = &Resampler::_CopyDouble2Int;
					break;
				case media_raw_audio_format::B_AUDIO_SHORT:
					fFunc = &Resampler::_CopyDouble2Short;
					break;
				case media_raw_audio_format::B_AUDIO_UCHAR:
					fFunc = &Resampler::_CopyDouble2UChar;
					break;
				case media_raw_audio_format::B_AUDIO_CHAR:
					fFunc = &Resampler::_CopyDouble2Char;
					break;
			}
			break;

		case media_raw_audio_format::B_AUDIO_INT:
			switch (destFormat) {
				case media_raw_audio_format::B_AUDIO_FLOAT:
					fFunc = &Resampler::_CopyInt2Float;
					break;
				case media_raw_audio_format::B_AUDIO_DOUBLE:
					fFunc = &Resampler::_CopyInt2Double;
					break;
				case media_raw_audio_format::B_AUDIO_INT:
					fFunc = &Resampler::_CopyInt2Int;
					break;
				case media_raw_audio_format::B_AUDIO_SHORT:
					fFunc = &Resampler::_CopyInt2Short;
					break;
				case media_raw_audio_format::B_AUDIO_UCHAR:
					fFunc = &Resampler::_CopyInt2UChar;
					break;
				case media_raw_audio_format::B_AUDIO_CHAR:
					fFunc = &Resampler::_CopyInt2Char;
					break;
			}
			break;

		case media_raw_audio_format::B_AUDIO_SHORT:
			switch (destFormat) {
				case media_raw_audio_format::B_AUDIO_FLOAT:
					fFunc = &Resampler::_CopyShort2Float;
					break;
				case media_raw_audio_format::B_AUDIO_DOUBLE:
					fFunc = &Resampler::_CopyShort2Double;
					break;
				case media_raw_audio_format::B_AUDIO_INT:
					fFunc = &Resampler::_CopyShort2Int;
					break;
				case media_raw_audio_format::B_AUDIO_SHORT:
					fFunc = &Resampler::_CopyShort2Short;
					break;
				case media_raw_audio_format::B_AUDIO_UCHAR:
					fFunc = &Resampler::_CopyShort2UChar;
					break;
				case media_raw_audio_format::B_AUDIO_CHAR:
					fFunc = &Resampler::_CopyShort2Char;
					break;
			}
			break;

		case media_raw_audio_format::B_AUDIO_UCHAR:
			switch (destFormat) {
				case media_raw_audio_format::B_AUDIO_FLOAT:
					fFunc = &Resampler::_CopyUChar2Float;
					break;
				case media_raw_audio_format::B_AUDIO_DOUBLE:
					fFunc = &Resampler::_CopyUChar2Double;
					break;
				case media_raw_audio_format::B_AUDIO_INT:
					fFunc = &Resampler::_CopyUChar2Int;
					break;
				case media_raw_audio_format::B_AUDIO_SHORT:
					fFunc = &Resampler::_CopyUChar2Short;
					break;
				case media_raw_audio_format::B_AUDIO_UCHAR:
					fFunc = &Resampler::_CopyUChar2UChar;
					break;
				case media_raw_audio_format::B_AUDIO_CHAR:
					fFunc = &Resampler::_CopyUChar2Char;
					break;
			}
			break;

		case media_raw_audio_format::B_AUDIO_CHAR:
			switch (destFormat) {
				case media_raw_audio_format::B_AUDIO_FLOAT:
					fFunc = &Resampler::_CopyChar2Float;
					break;
				case media_raw_audio_format::B_AUDIO_DOUBLE:
					fFunc = &Resampler::_CopyChar2Double;
					break;
				case media_raw_audio_format::B_AUDIO_INT:
					fFunc = &Resampler::_CopyChar2Int;
					break;
				case media_raw_audio_format::B_AUDIO_SHORT:
					fFunc = &Resampler::_CopyChar2Short;
					break;
				case media_raw_audio_format::B_AUDIO_UCHAR:
					fFunc = &Resampler::_CopyChar2UChar;
					break;
				case media_raw_audio_format::B_AUDIO_CHAR:
					fFunc = &Resampler::_CopyChar2Char;
					break;
			}
			break;
	}
}


Resampler::~Resampler()
{
}


void
Resampler::_Void(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	
}


void
Resampler::_CopyFloat2Float(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(float*)outputData = *(const float*)inputData;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyFloat2Double(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(double*)outputData = *(const float*)inputData;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyFloat2Int(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		float data = *(const float*)inputData;
		if (data <= -1.0f)
			*(int32*)outputData = INT32_MIN;
		else if (data >= 1.0f)
			*(int32*)outputData = INT32_MAX;
		else
			*(int32*)outputData = (int32)(data * INT32_MAX);

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}

void
Resampler::_CopyFloat2Short(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int16*)outputData = (int16)(*(const float*)inputData * 32767.0f);

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyFloat2UChar(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(uint8*)outputData = (uint8)(128.0f + *(const float*)inputData * 127.0f);

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyFloat2Char(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int8*)outputData = (int8)(*(const float*)inputData * 127.0f);

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyDouble2Float(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(float*)outputData = *(const double*)inputData;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyDouble2Double(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(double*)outputData = *(const double*)inputData;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyDouble2Int(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int32*)outputData = (int32)(*(const double*)inputData
			* (double)INT32_MAX);

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyDouble2Short(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int16*)outputData = (int16)(*(const double*)inputData * 32767.0f);

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyDouble2UChar(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(uint8*)outputData = (uint8)(128.0f + *(const double*)inputData * 127.0f);

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyDouble2Char(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int8*)outputData = (int8)(*(const double*)inputData * 127.0f);

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyShort2Float(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(float*)outputData = *(const int16*)inputData / 32767.0f;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyShort2Double(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(double*)outputData = *(const int16*)inputData / 32767.0;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyShort2Int(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int32*)outputData = (int32)*(const int16*)inputData << 16;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyShort2Short(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int16*)outputData = *(const int16*)inputData;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyShort2UChar(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(uint8*)outputData = 128 + (*(const int16*)inputData >> 8);

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyShort2Char(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int8*)outputData = *(const int16*)inputData >> 8;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyInt2Float(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(float*)outputData = *(const int32*)inputData / 2147483647.0f;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyInt2Double(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(double*)outputData = *(const int32*)inputData / 2147483647.0;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyInt2Int(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int32*)outputData = *(const int32*)inputData;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyInt2Short(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int16*)outputData = *(const int32*)inputData >> 16;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyInt2UChar(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(uint8*)outputData = 128 + (*(const int32*)inputData >> 24);

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyInt2Char(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(uint8*)outputData = *(const int32*)inputData >> 24;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyUChar2Float(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(float*)outputData = (*(const uint8*)inputData - 128) / 127.0f;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyUChar2Double(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(double*)outputData = (*(const uint8*)inputData - 128) / 127.0;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyUChar2Short(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int16*)outputData = (int16)(*(const uint8*)inputData - 128) << 8;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyUChar2Int(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int32*)outputData = (int32)(*(const uint8*)inputData - 128) << 24;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyUChar2UChar(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(uint8*)outputData = *(const uint8*)inputData;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyUChar2Char(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int8*)outputData = *(const uint8*)inputData - 128;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyChar2Float(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(float*)outputData = *(const int8*)inputData / 127.0f;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyChar2Double(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(double*)outputData = *(const int8*)inputData / 127.0;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyChar2Short(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int16*)outputData = ((int16)*(const int8*)inputData) << 8;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyChar2Int(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int32*)outputData = ((int16)*(const int8*)inputData) << 24;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyChar2UChar(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(uint8*)outputData = *(const int8*)inputData + 128;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}


void
Resampler::_CopyChar2Char(const void *inputData, uint32 inputStride,
	void *outputData, uint32 outputStride, uint32 sampleCount)
{
	while (sampleCount > 0) {
		*(int8*)outputData = *(const int8*)inputData;

		outputData = (void*)((uint8*)outputData + outputStride);
		inputData = (void*)((uint8*)inputData + inputStride);

		sampleCount--;
	}
}