/*	
 *	framsds.c
 *
 *	P/ECE S-DSP Emulator
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2004 Naoyuki Sawa
 *
 *	* Sun Jan 06 06:00:00 JST 2004 Naoyuki Sawa
 *	- 作成開始。
 */
#include "clip.h"

/****************************************************************************
 *
 ****************************************************************************/

void
sdsp_mix(SDSP* sdsp, short wbuff[/*count*/], int count)
{
#define MIXBUFLEN	64	/* 処理単位。大きい方が速いですが、スタック溢れに注意!! */

	static int mixbuf[MIXBUFLEN];	/* スタック溢れ回避のため、STATIC! */
	//
	int subcnt;
	int value;
	int i_voice;
	SDSPVOICE* voice;
	//
	int mvol = sdsp->mvol;
	short* dst = wbuff;
	int* src;

	/* 要求されたcountサンプルを、MIXBUFLENサンプルづつに分けて処理します。 */
	while(count > 0) {
		/* 何サンプル合成するか? */
		subcnt = count;
		if(subcnt > MIXBUFLEN) subcnt = MIXBUFLEN;
		count -= subcnt;

		/* まずクリア。 */
		memset(mixbuf, 0, sizeof(int) * subcnt);

		/* Voice-0〜7の出力を合成します。 */
		value = 0;
		for(i_voice = 0, voice = sdsp->voice; i_voice < 8; i_voice++, voice++) {
			sdsp_voice_mix(sdsp, voice, mixbuf, subcnt); /* 符号付き16bit */
		}
		/* 符号付き16bit×8 => 符号付き19bit */

		/* スケーリング処理。 */
		src = mixbuf;
		do {
			/* メインボリュームを反映します。 */
			value = *src++;
			value *= mvol; /* 符号付き19bit×符号なし8bit => 符号付き27bit */
			value >>= 27 - 16 - 1/*調整可*/;

			/* クリッピングして格納します。 */
			if(value < -0x7fff) value = -0x7fff;
			if(value >  0x7fff) value =  0x7fff;
			*dst++ = value;
		} while(--subcnt);
	}

#undef MIXBUFLEN
}

//※ぜんぜん未実装。とりあえずノコギリ波で試してみます。
void
sdsp_voice_mix(SDSP* sdsp, SDSPVOICE* voice, int* mixbuf, int count)
{
	int progress;
	int p;
	int offset;
	int value;

	if(!voice->vol) return;
	if(voice->state <= SDSVOICE_RELEASE) return;

	progress = voice->progress;
	p = voice->p;
	do {
		progress += p;
		offset = progress >> 11;
		value = (char)((offset & 31) << 3) << 8; /* 符号付き16bit */
		*mixbuf++ += value;
	} while(--count);
	voice->progress = progress;
}

