簡易プレイヤ


ys8に対応したのはいいのですが、久々に普通のoggを再生したところ、途中で止まって強制終了指定しまいました。

原因つきとめるのにかなり掛かりましたが修正したものを置きました。

まだalacには対応出来てません。
-50エラーだすので、なかなか理由わかんないし。

追記 2019.01.11
-50エラーは取れました。
単に、受け取るバッファサイズが大きかったようです。4096くらいにしたら取れました。
m_pAlacDecoder->mConfig.frameLength

ただ、再生すると、少しのノイズが乗り、
44100Hz/16bitのalacだとテンポが若干速くなり、ノイズが載るので、テンポさえなんとかすればたぶん正常になりそう。
192000Hz/24bitのalacだとテンポめちゃくちゃ遅くなり、ノイズがかなり載るので、
まだ設定忘れているところ有りそう。

元ソースはkb media pleyerの新仕様のkpiソース全部を使っています。

alac側

BOOL __fastcall KbAlacDecoder::Open(const _TCHAR *cszFileName, SOUNDINFO *pInfo)
{
	ZeroMemory(pInfo, sizeof(SOUNDINFO));
	FILE *fp;
#if UNICODE	
	fp = _wfopen(cszFileName, L"rb");
#else
	fp = fopen(cszFileName, _T("rb"));
#endif	
	if (!fp) {
		return FALSE;
	}

	buffer = NULL;
	buffer_size=0;


	m_callback.user_data = fp;
	m_pMp4ff = mp4ff_open_read(&m_callback);
	if (!m_pMp4ff) {
		m_callback.user_data = NULL;
		return 0;
	}
	if (mp4ff_get_decoder_config(m_pMp4ff, 0, &buffer, &buffer_size) != 0) {
		mp4ff_close(m_pMp4ff);
		m_callback.user_data = NULL;
		return 0;
	}
	m_pAlacDecoder = new ALACDecoder;
	if (m_pAlacDecoder->Init(buffer, buffer_size) != 0) {
		delete m_pAlacDecoder;
		free(buffer);
		mp4ff_close(m_pMp4ff);
		m_callback.user_data = NULL;
		return 0;
	}
	free(buffer);
	m_qwLastSample = mp4ff_get_track_duration(m_pMp4ff, 0);
	m_MediaInfo.dwSampleRate = m_pAlacDecoder->mConfig.sampleRate;
	m_MediaInfo.dwChannels = m_pAlacDecoder->mConfig.numChannels;
	m_MediaInfo.nBitsPerSample = m_pAlacDecoder->mConfig.bitDepth;
	m_MediaInfo.qwLength = kpi_SampleTo100ns(m_qwLastSample, m_MediaInfo.dwSampleRate);
	m_MediaInfo.dwSeekableFlags = KPI_MEDIAINFO::SEEK_FLAGS_SAMPLE;
	m_MediaInfo.dwUnitSample = m_pAlacDecoder->mConfig.frameLength;
	m_MediaInfo.dwCount = 1;
	m_MediaInfo.dwNumber = 1;

	pInfo->dwSamplesPerSec = m_pAlacDecoder->mConfig.sampleRate;
	pInfo->dwChannels = m_pAlacDecoder->mConfig.numChannels;
	pInfo->dwBitsPerSample = m_pAlacDecoder->mConfig.bitDepth;
	pInfo->dwLength = kpi_SampleTo100ns(m_qwLastSample, m_MediaInfo.dwSampleRate);
	pInfo->dwSeekable = 1;
	pInfo->dwUnitRender = (m_pAlacDecoder->mConfig.frameLength) / 2;
	
	m_nTrack = 0;
	m_nNumSampleId = mp4ff_num_samples(m_pMp4ff, 0);
	buffer = NULL;
	buffer_size = 0;
	m_BitBuffer.cur = NULL;
	return 1;
}
//////////////////////////////////////////////////////////////////////////////
void __fastcall KbAlacDecoder::Close(void)
{
	delete m_pAlacDecoder; m_pAlacDecoder = NULL;
	if (m_pMp4ff) {
		mp4ff_close(m_pMp4ff);
		m_pMp4ff = NULL;
	}

	if (m_callback.user_data) {
		FILE *fp = (FILE*)m_callback.user_data;
		fclose(fp);
		m_callback.user_data = NULL;
	}
	m_pSample = NULL;
	m_dwLastSample = 0;
	m_dwCurrentSample = 0;
	m_dwRemain = 0;
	m_dwSampleRate = 0;
	m_dwChannels = 0;
	m_nNumSampleId = 0;
	m_nCurrentSampleId = 0;
	m_nTrack = 0;

	m_callback.user_data = NULL;
	m_nNumSampleId = 0;
	m_nCurrentSampleId = 0;
	m_nTrack = 0;
}
//////////////////////////////////////////////////////////////////////////
DWORD __fastcall KbAlacDecoder::Render(BYTE *pBuffer, DWORD dwSizeSample)
{
	DWORD dwRetSample = 0;
	if (m_nCurrentSampleId < m_nNumSampleId) {
		BYTE *buffer = NULL;
		UINT buffer_size = 0;
		int rc = mp4ff_read_sample(m_pMp4ff, m_nTrack, m_nCurrentSampleId, &buffer, &buffer_size);
		m_nCurrentSampleId++;
		BitBufferInit(&m_BitBuffer, buffer, buffer_size);
	}
	return dwRetSample;
}

DWORD __fastcall KbAlacDecoder::Render2(BYTE *pBuffer, DWORD dwSizeSample, DWORD cnt)
{
	DWORD dwRetSample = 0;
	if (m_nCurrentSampleId < m_nNumSampleId) {
		DWORD dwSample = 0;
		//BitBufferInit(&m_BitBuffer, buffer, buffer_size);
		int ret = m_pAlacDecoder->Decode(&m_BitBuffer, pBuffer+cnt, dwSizeSample, m_MediaInfo.dwChannels, (uint32_t*)&dwSample);
		dwRetSample = dwSample;
	}
	return dwRetSample;
}


int __fastcall KbAlacDecoder::SetPosition(DWORD dwPos)
{
	if (dwPos == 0 && m_nCurrentSampleId == 0) {//既に先頭位置にある
												//なくても問題ないが、無駄なので
		return 0;
	}
	int64_t i64PosSample = MulDiv(dwPos, m_dwSampleRate, 1000);
	//↑目的の位置をサンプル単位にしたもの

	int nStartId = 0;
	int nEndId = m_nNumSampleId;
	int64_t i64CurPos;
	while (1) {
		//2分探索で目的の位置を探す(一発で見つける方法が分からないので)
		//mp4ff_find_sample を使えば一発で行けそうだけど使い方が分からない
		int nId = nStartId + (nEndId - nStartId) / 2;
		i64CurPos = mp4ff_get_sample_position(m_pMp4ff, m_nTrack, nId);
		if (i64CurPos == i64PosSample) {//滅多に成立しない
			nStartId = nEndId = nId;
		}
		else if (i64CurPos > i64PosSample) {
			nEndId = nId - 1;
		}
		else {
			nStartId = nId + 1;
		}
		if (nEndId <= nStartId) {
			break;
		}
	}
	m_nCurrentSampleId = nEndId - 1;//1つ手前にシークする
	if (m_nCurrentSampleId >= m_nNumSampleId) {
		m_nCurrentSampleId = m_nNumSampleId - 1;
	}
	if (m_nCurrentSampleId < 0) {
		m_nCurrentSampleId = 0;
	}
	m_pSample = NULL;
	m_dwRemain = 0;
	//足りない分を最大1秒だけ空読み
	//KbMedia Player 本体が必要に応じてやるので実際は不要
	m_dwCurrentSample = mp4ff_get_sample_position(m_pMp4ff, m_nTrack, m_nCurrentSampleId);
	DWORD dwCurPosMS = MulDiv(m_dwCurrentSample, 1000, m_dwSampleRate);
	DWORD dwDeltaMS = dwPos - dwCurPosMS;
	if (dwDeltaMS > 1000) {
		dwDeltaMS = 1000;
	}
	DWORD dwDeltaSample = MulDiv(dwDeltaMS, m_dwSampleRate, 1000);
	DWORD dwDeltaBytes = dwDeltaSample * 2 * m_dwChannels;
	if (dwDeltaBytes) {
		BYTE *pBuffer = (BYTE*)malloc(dwDeltaBytes);
		dwDeltaBytes = Render(pBuffer, dwDeltaBytes);
		dwDeltaMS = MulDiv(dwDeltaBytes / 2 / m_dwChannels, 1000, m_dwSampleRate);
		dwPos = dwCurPosMS + dwDeltaMS;
		free(pBuffer);
	}
	return dwPos;
}

//MP4ファイル読み込みコールバック関数
uint32_t _read_callback(void *user_data, void *buffer, uint32_t length)
{
	return ((CFile*)user_data)->Read(buffer, length);
}

//MP4ファイルシークコールバック関数
uint32_t _seek_callback(void *user_data, uint64_t position)
{
	return (uint32_t)((CFile*)user_data)->Seek(position, CFile::begin);
}

class m4a
{
public:
	static HKMP WINAPI Open(const _TCHAR *cszFileName, SOUNDINFO *pInfo)
	{//MP4 コンテナに格納されていれば KbMp4AacDecoder
	 //MP4 コンテナに格納されなければ KbAacDecoder
	 //を作成し、そのポインタを返す
		FILE *fp;
#if UNICODE	
		fp = _wfopen(cszFileName, _T("rb"));
#else
		fp = fopen(cszFileName, _T("rb"));
#endif	
		if (!fp) {
			return FALSE;
		}

		IKbAacDecoder *pAAC;
		mp4ff_callback_t callback = { 0 };
		callback.read = read_callback;
		callback.seek = seek_callback;
		callback.user_data = fp;
		mp4ff_t *pMp4ff = mp4ff_open_read(&callback);
		if (!pMp4ff) {
			KbAacDecoder *pAacDecoder = new KbAacDecoder;
			DWORD dwCount = pAacDecoder->Open(cszFileName, pInfo);
			if (dwCount) {
				pAAC = pAacDecoder;
				return pAAC;
			}
			else {
				pAacDecoder->Close();
			}
		}
		else
		 {
			if (mp4ff_total_tracks(pMp4ff) > 0) {
				fseek(fp,0, SEEK_SET);
				char a[0x400];
				char b;
				CString str;
				int flag = 0;
				fread(a,0x400,1,fp);
				//if (strstr(a,"alac")==0) {
				//	flag = 1;
				//}
				//if (flag == 0){ //TRACK_AUDIO){
				//	pAAC = new KbMp4AacDecoder;
				//}
				//else if (flag == 1) {//TRACK_AUDIO_ALAC
				//	pAAC = new KbAlacDecoder;
				//}
				if (mp4ff_total_tracks(pMp4ff) > 0) {
					int type = mp4ff_get_track_type(pMp4ff, 0);
					if (type == 1) {//TRACK_AUDIO)
						pAAC = new KbMp4AacDecoder;
					}
					else if (type == 4) {//TRACK_AUDIO_ALAC
						pAAC = new KbAlacDecoder;
					}
				}
			}
		}
		fclose(fp);

		if (pAAC->Open(cszFileName, pInfo)) {
			return pAAC;
		}
		delete pAAC;
		return NULL;
	}

	static void WINAPI Close(HKMP hKMP)
	{
		if (hKMP) {
			IKbAacDecoder *pAAC = (IKbAacDecoder*)hKMP;
			delete pAAC;
			hKMP = NULL;
		}
	}

	static DWORD WINAPI Render(HKMP hKMP, BYTE* Buffer, DWORD dwSize)
	{
		if (!hKMP)return 0;
		IKbAacDecoder *pAAC = (IKbAacDecoder*)hKMP;
		return pAAC->Render(Buffer, dwSize);
	}

	static DWORD WINAPI Render2(HKMP hKMP, BYTE* Buffer, DWORD dwSize,DWORD cnt3)
	{
		if (!hKMP)return 0;
		IKbAacDecoder *pAAC = (IKbAacDecoder*)hKMP;
		return pAAC->Render2(Buffer, dwSize,cnt3);
	}

	static BYTE* WINAPI Buf(HKMP hKMP)
	{
		if (!hKMP)return 0;
		IKbAacDecoder *pAAC = (IKbAacDecoder*)hKMP;
		return pAAC->buffer;
	}

	static DWORD WINAPI SetPosition(HKMP hKMP, DWORD dwPos)
	{
		if (!hKMP)return 0;
		IKbAacDecoder *pAAC = (IKbAacDecoder*)hKMP;
		return pAAC->SetPosition(dwPos);
	}
};

読み込み側

int playwavm4a(BYTE* bw, int old, int l1, int l2)
{
	//データ読み込み
	int rrr = readm4a(bw + old, l1);
	playb += (l1 + l2) / ((wavch == 1 || wavch == 2) ? 4 : (wavch * 2));
//	if (oggsize / ((wavch == 1) ? 1 : 1) - 44100 < = playb * 4) {
	//	if (savedata.saveloop == FALSE) {
		//	l1 = rrr;  fade1 = 1;
//			return l1;
	//	}
	//}
	if (l1 != rrr) {
		if (endf == 1) {
			l1 = rrr; fade1 = 1;
		}
		else {
			loopcnt++;
			playb = loop1;
			m4a_.SetPosition(og->kmp, 0);
			readm4a(bw + old + rrr, l1 - rrr);
		}
	}
	if (l2) {
		rrr = readm4a(bw, l2);
		if (l2 != rrr) {
			if (endf == 1) {
				l2 = rrr; fade1 = 1;
			}
			else {
				loopcnt++;
				playb = loop1;
				m4a_.SetPosition(og->kmp, 0);
				readm4a(bw + rrr, (int)l2 - rrr);
			}
		}
	}
	return l1 + l2;
}

int readm4a(BYTE*bw, int cnt)
{
	_set_se_translator(trans_func);
	DWORD cnt1 = og->sikpi.dwUnitRender * 2, cnt2 = (DWORD)cnt, cnt4; if (cnt1 == 0) cnt1 = 1024;
	m4a_.Render(og->kmp, (BYTE*)bufkpi, cnt1);
	DWORD r = 0;
	 {
		for (;;) {
			if (cnt2 < = cnt3) { r = 1; break; }
			r = m4a_.Render2(og->kmp, (BYTE*)bufkpi, cnt1,cnt3);
			if (r == 0) break;
			cnt3 += r;
		}
		if (m4a_.Buf(og->kmp) != NULL) {
			free(m4a_.Buf(og->kmp));
		}
		cnt4 = cnt3;
		if (r == 0) cnt = 0;
		memcpy(bufkpi2, bufkpi, cnt);
		unsigned short *bf1, *bf2; bf1 = (unsigned short*)bw; bf2 = (unsigned short*)bufkpi2;
		//		int fw = playb % (wavch);
		//		bf2 += fw;
		int cnt1 = cnt / 2;
		switch (wavch)
		{
		case 1:
		case 2:
			memcpy(bw, bufkpi, cnt);
			break;
		case 3: // 2.1   
			for (int sample = 0; sample < cnt1; sample += wavch)
			{
				int ChannelMap[3] = { 2,3,1 };
				for (int ch = 0; ch < wavch; ch++)
				{
					*bf1++ = bf2[ChannelMap[ch] - 1];
				}
				bf2 += wavch;
			}
			break;
		case 4: // Quad   
			for (int sample = 0; sample < cnt1; sample += wavch)
			{
				int ChannelMap[4] = { 2,3,1,4 };
				for (int ch = 0; ch < wavch; ch++)
				{
					*bf1++ = bf2[ChannelMap[ch] - 1];
				}
				bf2 += wavch;
			}
			break;
		case 5: // Surround   
			for (int sample = 0; sample < cnt1; sample += wavch)
			{
				int ChannelMap[5] = { 2,3,1,4,5 };
				for (int ch = 0; ch < wavch; ch++)
				{
					*bf1++ = bf2[ChannelMap[ch] - 1];
				}
				bf2 += wavch;
			}
			break;
		case 6: // 5.1   
			for (int sample = 0; sample < cnt1; sample += wavch)
			{
				int ChannelMap[6] = { 2,3,1,6,4,5 };
				for (int ch = 0; ch < wavch; ch++)
				{
					*bf1++ = bf2[ChannelMap[ch] - 1];
				}
				bf2 += wavch;
			}
			break;
		}
		if (cnt2 <= cnt3) {
			cnt3 -= cnt2;
			if (cnt3 != 0)	memcpy(bufkpi, bufkpi + cnt2, cnt3);
		}
		Int24 *b24c;
		b24c = (Int24*)bw;
		short *b, c;
		b = (short*)bw;
		if (wavsam == 24) {
			for (int i = 0; i < cnt / 3; i++) {
				int c4 = b24c[i];
				c4 = (int)((float)c4 * ((float)savedata.kakuVal / 100.0f));
				b24c[i] = c4;
			}
		}
		else {
			for (int i = 0; i < cnt / 2; i++) {
				int c = (int)b[i];
				c = (int)((float)c * ((float)savedata.kakuVal / 100.0f));
				b[i] = (short)c;
			}
		}
		if (wavsam == 24) {
			for (int i = 0; i < cnt / 3; i++) {
				int c4 = b24c[i];
				if (savedata.mp3 == 2)	c4 = (int)((float)c4 * 2.0f);
				else if (savedata.mp3 == 4) c4 = (int)((float)c4 * 3.0f);
				else if (savedata.mp3 == 8) c4 = (int)((float)c4 * 4.0f);
				else if (savedata.mp3 == 16) c4 = (int)((float)c4 * 5.0f);
				if (c4 >  8388607)c4 = 8388607;
				if (c4 < -8388608)c4 = -8388608;
				b24c[i] = c4;
			}
		}
		else {
			for (int i = 0; i < cnt / 2; i++) {
				int c = (int)b[i];
				if (savedata.mp3 == 2)	c = (int)((float)b[i] * 1.5f);
				else if (savedata.mp3 == 3) c = (int)((float)b[i] * 2.0f);
				else if (savedata.mp3 == 4) c = (int)((float)b[i] * 2.5f);
				else if (savedata.mp3 == 5) c = (int)((float)b[i] * 3.0f);
				if (c >= 32768)c = 32767;
				if (c <= -32767)c = -32766;
				b[i] = (short)c;
			}
		}
		fade += fadeadd; if (fade&lt;0.0001) { fade = 0.0; fadeadd = 0; }
		//fadeを三乗して計算密度を変更
		if (wavsam == 24) {
			float c4;
			int c5;
			for (int i = 0; i < cnt / 3; i++) {
				c5 = b24c[i]; c4 = (float)c5;
				c4 = c4 * fade * fade; c5 = (int)c4;
				b24c[i] = c5;
			}
		}
		else {
			for (int i = 0; i < cnt / 2; i++) { c = b[i]; c = (short)(((float)c) * fade * fade); b[i] = c; }
		}
		if ((UINT)wl<(UINT)0x7fff0000) {
			if (cc1 == 1)	cc.Write(bw, cnt);
			wl += cnt;
		}
		lenl += cnt;
	}
	if (cnt4<cnt) cnt = cnt4;
	return cnt;
}

分かる方いましたら、返信かchacha@oohara.jpへメール下さいませm(__)m

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください