From c85b9f372976213500ea077f238425319cc7971a Mon Sep 17 00:00:00 2001 From: Byurrer <byurrer@mail.ru> Date: Wed, 3 Jun 2020 22:06:47 +0300 Subject: [PATCH] Fixed coding in ogg-vorbis --- source/oggplugin/AudioCodecOgg.cpp | 125 +++++++++++++++------------- source/wavplugin/AudioCodecWave.cpp | 2 +- source/xEngine/Engine.cpp | 53 +++++++----- source/xSound/AudioConverter.h | 5 ++ source/xSound/SoundSystem.cpp | 24 +++++- 5 files changed, 125 insertions(+), 84 deletions(-) diff --git a/source/oggplugin/AudioCodecOgg.cpp b/source/oggplugin/AudioCodecOgg.cpp index 45d980cc9..3e90c267d 100644 --- a/source/oggplugin/AudioCodecOgg.cpp +++ b/source/oggplugin/AudioCodecOgg.cpp @@ -101,7 +101,7 @@ bool XMETHODCALLTYPE CAudioCodecOgg::open(const char *szFile, const char *szArg, { IFile *pFile = m_pFileSystem->openFile(szFile, (forSave ? FILE_MODE_WRITE : FILE_MODE_READ)); - if (!pFile || !ppTarget) + if (!pFile || !ppTarget || (forSave && (!szArg && strcasecmp(szArg, getFormat()) != 0))) return false; OggVorbis_File *pVoFile = NULL; @@ -284,16 +284,14 @@ bool XMETHODCALLTYPE CAudioCodecTargetOgg::encode(IXBuffer *pBufferPCM, AudioRaw //инициализация кодировщика (статических данных) с переменным битрейтом (variable bitrate) vorbis_info_init(&oVoInfo); - iRetCode = vorbis_encode_init_vbr(&oVoInfo, pOutDesc->u8Channels, pOutDesc->uSampleRate, 0.1); + if ((iRetCode = vorbis_encode_init_vbr(&oVoInfo, pOutDesc->u8Channels, pOutDesc->uSampleRate, 0.2))) + return false; /* можно заюзать усредненный битрейт (average bitrate): - iRetCode = vorbis_encode_init(&vi,pOutDesc->u8Channels, pOutDesc->uSampleRate,-1,128000,-1); - * но в данной реализации пусть кодировщик сам разбирается :) + iRetCode = vorbis_encode_init(&vi,pOutDesc->u8Channels, pOutDesc->uSampleRate,-1,128000,-1); + но в данной реализации пусть кодировщик сам разбирается :) */ - if(iRetCode) - return false; - //инициализируем комментарий vorbis_comment_init(&oVoComment); vorbis_comment_add_tag(&oVoComment, "ENCODER", "SkyXEngine plugin [class 'codec_ogg']"); @@ -315,11 +313,8 @@ bool XMETHODCALLTYPE CAudioCodecTargetOgg::encode(IXBuffer *pBufferPCM, AudioRaw //************************************************** //сброс заголовков в логический поток данных - while(!iEndOfStream) + while (ogg_stream_flush(&oOggStream, &oOggPage)) { - iRetCode = ogg_stream_flush(&oOggStream, &oOggPage); - if(iRetCode == 0) - break; m_pFile->writeBin(oOggPage.header, oOggPage.header_len); m_pFile->writeBin(oOggPage.body, oOggPage.body_len); } @@ -341,88 +336,100 @@ bool XMETHODCALLTYPE CAudioCodecTargetOgg::encode(IXBuffer *pBufferPCM, AudioRaw но так делать не надо, потому что внутри vorbis_analysis_wrote выделяется память на стеке по общему количеству блоков это может привести к переполнению стека */ + /* но разделять на блоки и передавать таким образом данные тоже нельзя + */ /* получаем выделенный массив (по количеству каналов) массивов (по количеству семплов) aaBuffer[iChannel][iSample] */ /*float **aaBuffer = vorbis_analysis_buffer(&oVoMainState, iCountBlocks); + int iCurrSample = 0; //заполняем выделенный float массив нормализованными данными [-1.0, 1.0] for(int i = 0; i < iCountBlocks ; ++i) { for(int iChannels = 0; iChannels<pOutDesc->u8Channels; ++iChannels) { - int16_t i16Sample = ((int16_t*)pData)[i]; - aaBuffer[iChannels][i]=float(i16Sample)/32768.f; + iCurrSample = i * pOutDesc->u8Channels + iChannels; + int16_t i16Sample = ((int16_t*)pData)[iCurrSample]; + aaBuffer[iChannels][i] = float(i16Sample) / 32768.f; } } //сообщаем кодировщику что поступили данные для записи vorbis_analysis_wrote(&oVoMainState, iCountBlocks);*/ - //циклом (частями) передаем данные кодировщику - while (iCountReadedBlocks < iCountBlocks) + //************************************************** + // запись семплов + + //если еще не дошли до конца битового потока, тогда продолжаем запись + while(!iEndOfStream) { - //количество уже прочитанных сэмплов + //количество прочитанных семплов uint32_t uCountReadedSamples = (iCountReadedBlocks*pOutDesc->u8Channels); - //количество блоков для текущей итерации int iCurrBlocks = iPartBlocks; if (iCountBlocks - iCountReadedBlocks < iPartBlocks) iCurrBlocks = iCountBlocks - iCountReadedBlocks; - float **aaBuffer = vorbis_analysis_buffer(&oVoMainState, iCurrBlocks); - - for (int i = 0; i < iCurrBlocks; ++i) + //если есть блоки для записи + if (iCurrBlocks > 0) { - for (int iChannels = 0; iChannels<pOutDesc->u8Channels; ++iChannels) + /* получаем выделенный массив (по количеству каналов) массивов (по количеству семплов) + aaBuffer[iChannel][iSample] + */ + float **aaBuffer = vorbis_analysis_buffer(&oVoMainState, iCurrBlocks); + int iCurrSample = 0; + + //запись блоков + for (int i = 0; i < iCurrBlocks; ++i) { - int16_t i16Sample = ((int16_t*)pData)[uCountReadedSamples + i]; - aaBuffer[iChannels][i] = float(i16Sample) / 32768.f; + for (int iChannels = 0; iChannels < pOutDesc->u8Channels; ++iChannels) + { + iCurrSample = uCountReadedSamples + i * pOutDesc->u8Channels + iChannels; + int16_t i16Sample = ((int16_t*)pData)[iCurrSample]; + aaBuffer[iChannels][i] = float(i16Sample) / 32768.f; + } } - } - vorbis_analysis_wrote(&oVoMainState, iCurrBlocks); - iCountReadedBlocks += iCurrBlocks; - } - - - //************************************************** - // запись семплов - - //если еще не дошли до конца битового потока, тогда продолжаем запись - while(!iEndOfStream) - { - /*разбивка несжатых данных на блоки, если не удалось, тогда сообщаем что данных больше не будет - если не сообщить об этом, то не все данные будут записаны, не получится дойти до конца битового потока, потому что запись идет постраничная и последняя неполня страница не будет записана - */ - if (vorbis_analysis_blockout(&oVoMainState, &oVoDataBlock) != 1) + //сообщаем кодировщику что поступили данные для записи + vorbis_analysis_wrote(&oVoMainState, iCurrBlocks); + iCountReadedBlocks += iCurrBlocks; + } + else { + /* сообщаем что данных больше не будет + если не сообщить об этом, то не все данные будут записаны, не получится дойти до конца битового потока, + потому что запись идет постраничная и последняя неполная страница не будет записана + */ vorbis_analysis_wrote(&oVoMainState, 0); } - //поиск режима кодирования и отправка блока на кодировку - vorbis_analysis(&oVoDataBlock, NULL); - vorbis_bitrate_addblock(&oVoDataBlock); - - //получение следующего доступного пакета - while(vorbis_bitrate_flushpacket(&oVoMainState, &oOggPacket)) + while (vorbis_analysis_blockout(&oVoMainState, &oVoDataBlock) == 1) { - //отправка пакета в битовый поток - ogg_stream_packetin(&oOggStream, &oOggPacket); + //поиск режима кодирования и отправка блока на кодировку + vorbis_analysis(&oVoDataBlock, NULL); + vorbis_bitrate_addblock(&oVoDataBlock); - while(!iEndOfStream) + //получение следующего доступного пакета + while (vorbis_bitrate_flushpacket(&oVoMainState, &oOggPacket)) { - //формирование пакетов в страницы и отправка в битовый поток - int result=ogg_stream_pageout(&oOggStream, &oOggPage); - if(result==0) - break; - - m_pFile->writeBin(oOggPage.header, oOggPage.header_len); - m_pFile->writeBin(oOggPage.body, oOggPage.body_len); - - //если все записано (находимся в конце битового потока), сообщаем о завершении - if(ogg_page_eos(&oOggPage)) - iEndOfStream=1; + //отправка пакета в битовый поток + ogg_stream_packetin(&oOggStream, &oOggPacket); + + while (!iEndOfStream) + { + //формирование пакетов в страницы и отправка в битовый поток + int result = ogg_stream_pageout(&oOggStream, &oOggPage); + if (result == 0) + break; + + m_pFile->writeBin(oOggPage.header, oOggPage.header_len); + m_pFile->writeBin(oOggPage.body, oOggPage.body_len); + + //если все записано (находимся в конце битового потока), сообщаем о завершении + if (ogg_page_eos(&oOggPage)) + iEndOfStream = 1; + } } } } diff --git a/source/wavplugin/AudioCodecWave.cpp b/source/wavplugin/AudioCodecWave.cpp index 07360e982..3f4330601 100644 --- a/source/wavplugin/AudioCodecWave.cpp +++ b/source/wavplugin/AudioCodecWave.cpp @@ -13,7 +13,7 @@ bool XMETHODCALLTYPE CAudioCodecWave::open(const char *szFile, const char *szArg { IFile *pFile = m_pFileSystem->openFile(szFile, (forSave ? FILE_MODE_WRITE : FILE_MODE_READ)); - if (!pFile || !ppTarget) + if (!pFile || !ppTarget && (forSave && (!szArg && strcasecmp(szArg, getFormat()) != 0))) return false; AudioRawDesc oDesc; diff --git a/source/xEngine/Engine.cpp b/source/xEngine/Engine.cpp index bbd626b7d..3c31cdfb5 100644 --- a/source/xEngine/Engine.cpp +++ b/source/xEngine/Engine.cpp @@ -161,6 +161,35 @@ bool XMETHODCALLTYPE CEngine::initGraphics(XWINDOW_OS_HANDLE hWindow, IXEngineCa SSInput_0Create("sxinput", (HWND)hWindow, false); LibReport(REPORT_MSG_LEVEL_NOTICE, "LIB input initialized\n"); + + + // init sound + AudioRawDesc oAudioDesc; + oAudioDesc.u8Channels = 2; + oAudioDesc.fmtSample = AUDIO_SAMPLE_FMT_SINT16; + oAudioDesc.uSampleRate = 44100; + oAudioDesc.calc(); + + /*IXSoundSystem *pSound = (IXSoundSystem*)(m_pCore->getPluginManager()->getInterface(IXSOUNDSYSTEM_GUID)); + IXSoundLayer *pMasterLayer = pSound->createMasterLayer(&oAudioDesc, "master"); + pMasterLayer->play(true); + IXSoundPlayer *pPlayer = pMasterLayer->newSoundPlayer("sounds/guitar_10.ogg", SOUND_DTYPE_2D); + pPlayer->play();*/ + /*IXSoundEmitter *pEmitter = pMasterLayer->newSoundEmitter("sounds/ak74_shoot.ogg", SOUND_DTYPE_2D); + pEmitter->play();*/ + + /*while (1) + { + if (GetAsyncKeyState('I')) + { + pEmitter->play(); + Sleep(100); + } + }*/ + + + + // init graphics Core_0RegisterCVarInt("r_win_width", 800, "Размер окна по горизонтали (в пикселях)", FCVAR_NOTIFY_OLD); Core_0RegisterCVarInt("r_win_height", 600, "Размер окна по вертикали (в пикселях)", FCVAR_NOTIFY_OLD); @@ -200,29 +229,7 @@ bool XMETHODCALLTYPE CEngine::initGraphics(XWINDOW_OS_HANDLE hWindow, IXEngineCa LibReport(REPORT_MSG_LEVEL_NOTICE, "LIB render initialized\n"); - // init sound - AudioRawDesc oAudioDesc; - oAudioDesc.u8Channels = 2; - oAudioDesc.fmtSample = AUDIO_SAMPLE_FMT_SINT16; - oAudioDesc.uSampleRate = 44100; - oAudioDesc.calc(); - - IXSoundSystem *pSound = dynamic_cast<IXSoundSystem*>(m_pCore->getPluginManager()->getInterface(IXSOUNDSYSTEM_GUID)); - IXSoundLayer *pMasterLayer = pSound->createMasterLayer(&oAudioDesc, "master"); - pMasterLayer->play(true); - /*IXSoundPlayer *pPlayer = pMasterLayer->newSoundPlayer("sounds/guitar_10.ogg", SOUND_DTYPE_2D); - pPlayer->play();*/ - /*IXSoundEmitter *pEmitter = pMasterLayer->newSoundEmitter("sounds/ak74_shoot.ogg", SOUND_DTYPE_2D); - pEmitter->play(); - - while (1) - { - if (GetAsyncKeyState('I')) - { - pEmitter->play(); - Sleep(100); - } - }*/ + LibReport(REPORT_MSG_LEVEL_NOTICE, "LIB sound initialized\n"); diff --git a/source/xSound/AudioConverter.h b/source/xSound/AudioConverter.h index 195788d3e..1284fb95b 100644 --- a/source/xSound/AudioConverter.h +++ b/source/xSound/AudioConverter.h @@ -18,6 +18,11 @@ inline bool AudioResampling(void *pIn, AudioRawDesc *pInDesc, IXBuffer *pOut, Au if (pToDesc->uSampleRate == pInDesc->uSampleRate) return false; + /*pOut->alloc(pInDesc->uSize); + memcpy(pOut->get(), pIn, pInDesc->uSize); + return true;*/ + + BYTE *pSrcData = 0; if (pOut->size() > 0) diff --git a/source/xSound/SoundSystem.cpp b/source/xSound/SoundSystem.cpp index a01a46a61..46fb577ca 100644 --- a/source/xSound/SoundSystem.cpp +++ b/source/xSound/SoundSystem.cpp @@ -45,12 +45,16 @@ CSoundSystem::~CSoundSystem() mem_release(m_pMasterLayer); } +//************************************************************************** + void XMETHODCALLTYPE CSoundSystem::update(const float3 &vListenerPos, const float3 &vListenerDir, const float3 &vListenerUp) { if(m_pMasterLayer) m_pMasterLayer->update(); } +//************************************************************************** + IXSoundLayer* XMETHODCALLTYPE CSoundSystem::createMasterLayer(const AudioRawDesc *pDesc, const char *szName) { if(m_pMasterLayer) @@ -73,11 +77,15 @@ IXSoundLayer* XMETHODCALLTYPE CSoundSystem::createMasterLayer(const AudioRawDesc return pLayer; } +//************************************************************************** + IXCore* CSoundSystem::getCore() const { return m_pXCore; } +//************************************************************************** + IXAudioCodecTarget* CSoundSystem::getCodecTarget(const char *szName) { if(!m_pMasterLayer) @@ -121,6 +129,7 @@ IXAudioCodecTarget* CSoundSystem::getCodecTarget(const char *szName) if(oDescSnd.uSampleRate == oDescMaster.uSampleRate) return pTarget; + //если кодек может сохранять, тогда пересохраняем файл if(pCodec->canSave()) { @@ -156,8 +165,11 @@ IXAudioCodecTarget* CSoundSystem::getCodecTarget(const char *szName) //ищем первый попавшийся кодек который может записывать IXAudioCodec *pFullCodec = getCodecSave(); - if(!pFullCodec) + if (!pFullCodec) + { + LibReport(REPORT_MSG_LEVEL_ERROR, "Not found codec for coding, file '%s' does not match of parameters master buffer\n", szPath); return NULL; + } //создаем путь до файла в кэше String sCachePath = String(SOUND_CACHE) + "/"+ szPath; @@ -226,6 +238,8 @@ IXAudioCodecTarget* CSoundSystem::getCodecTarget(const char *szName) return pTarget2; } +//************************************************************************** + void CSoundSystem::addCodec(const char *szFmt, IXAudioCodec *pCodec) { if(!szFmt || !pCodec) @@ -234,16 +248,22 @@ void CSoundSystem::addCodec(const char *szFmt, IXAudioCodec *pCodec) m_mapCodecs[szFmt] = pCodec; } +//************************************************************************** + IAudioBufferEx* CSoundSystem::createMasterBuffer(AudioRawDesc *pDesc) { return m_pAudio->createMasterBuffer(pDesc); } +//************************************************************************** + bool CSoundSystem::supportedDesc(const AudioRawDesc *pDesc, AB_TYPE type) { return m_pAudio->supportedDesc(pDesc, type); } +//************************************************************************** + IXSoundLayer* XMETHODCALLTYPE CSoundSystem::findLayer(const char *szName) { if(!szName) @@ -255,6 +275,8 @@ IXSoundLayer* XMETHODCALLTYPE CSoundSystem::findLayer(const char *szName) return m_pMasterLayer->findLayer(szName); } +//************************************************************************** + IXAudioCodec* CSoundSystem::getCodecSave() { for (mapcodec::Iterator i = m_mapCodecs.begin(); i != m_mapCodecs.end(); i++) -- GitLab