CacheGroup* BuildCacheGroup(Config& config, const string& name, bool isTerminal) { CacheGroup* cgp = new CacheGroup; CacheGroup& cg = *cgp; string prefix = "sys.caches." + name + "."; bool isPrefetcher = config.get<bool>(prefix + "isPrefetcher", false); if (isPrefetcher) { //build a prefetcher group uint32_t prefetchers = config.get<uint32_t>(prefix + "prefetchers", 1); cg.resize(prefetchers); for (vector<BaseCache*>& bg : cg) bg.resize(1); for (uint32_t i = 0; i < prefetchers; i++) { stringstream ss; ss << name << "-" << i; g_string pfName(ss.str().c_str()); cg[i][0] = new StreamPrefetcher(pfName); } return cgp; } uint32_t size = config.get<uint32_t>(prefix + "size", 64*1024); uint32_t banks = config.get<uint32_t>(prefix + "banks", 1); uint32_t caches = config.get<uint32_t>(prefix + "caches", 1); uint32_t bankSize = size/banks; if (size % banks != 0) { panic("%s: banks (%d) does not divide the size (%d bytes)", name.c_str(), banks, size); } cg.resize(caches); for (vector<BaseCache*>& bg : cg) bg.resize(banks); for (uint32_t i = 0; i < caches; i++) { for (uint32_t j = 0; j < banks; j++) { stringstream ss; ss << name << "-" << i; if (banks > 1) { ss << "b" << j; } g_string bankName(ss.str().c_str()); uint32_t domain = (i*banks + j)*zinfo->numDomains/(caches*banks); //(banks > 1)? nextDomain() : (i*banks + j)*zinfo->numDomains/(caches*banks); cg[i][j] = BuildCacheBank(config, prefix, bankName, bankSize, isTerminal, domain); } } return cgp; }
void CSampleBank::load(bool async) { // TODO : add async loading support ! CSampleBankManager::TVirtualBankCont::iterator it(_SampleBankManager->m_VirtualBanks.find(_Name)); if (it != _SampleBankManager->m_VirtualBanks.end()) { // this is a virtual sample bank ! nlinfo("Loading virtual sample bank %s", CStringMapper::unmap(_Name).c_str()); const CAudioMixerUser::TBackgroundFlags &flags = _SampleBankManager->m_AudioMixer->getBackgroundFlags(); for (uint i=0; i<it->second.size(); ++i) { if (flags.Flags[it->second[i].Filter]) { CSampleBank *bank = _SampleBankManager->findSampleBank(it->second[i].BankName); if (bank) bank->load(async); } } } //nlinfo("Loading sample bank %s %", CStringMapper::unmap(_Name).c_str(), async?"":"Asynchronously"); vector<string> filenames; // vector<string>::iterator iter; if (_Loaded) { nlwarning("Trying to load an already loaded bank : %s", CStringMapper::unmap(_Name).c_str ()); return; } // Load the sample bank from the builded sample_bank file. string bankName(CStringMapper::unmap(_Name)+".sample_bank"); string filename = CPath::lookup(bankName, false); if (filename.empty()) { nlwarning("Could not find sample bank [%s]", bankName.c_str()); return; } try { CIFile sampleBank(filename); CAudioMixerUser::TSampleBankHeader sbh; sampleBank.serial(sbh); _LoadingDone = false; sint32 seekStart = sampleBank.getPos(); uint8 *data = 0; uint i; for (i=0; i<sbh.Name.size(); ++i) { IBuffer *ibuffer = _SampleBankManager->m_AudioMixer->getSoundDriver()->createBuffer(); nlassert(ibuffer); TStringId nameId = CStringMapper::map(CFile::getFilenameWithoutExtension(sbh.Name[i])); ibuffer->setName(nameId); /* { sint16 *data16 = new sint16[sbh.NbSample[i]]; IBuffer::TADPCMState state; state.PreviousSample = 0; state.StepIndex = 0; uint count =0; for (count=0; count+1024<sbh.NbSample[i]; count+=1024) { IBuffer::decodeADPCM(data+count/2, data16+count, 1024, state); } IBuffer::decodeADPCM(data+count/2, data16+count, sbh.NbSample[i]-count, state); state.PreviousSample = 0; state.StepIndex = 0; sint16 *data16_2 = new sint16[sbh.NbSample[i]]; IBuffer::decodeADPCM(data, data16_2, sbh.NbSample[i], state); for (uint j=0; j<sbh.NbSample[i]; ++j) { if (data16[j] != data16_2[j]) { nlwarning("Sample differ at %u", j); } } _SoundDriver->readRawBuffer(ibuffer, sbh.Name[i], (uint8*)data16, sbh.NbSample[i]*2, Mono16, sbh.Freq[i]); delete [] data16; delete [] data16_2; } */ if (_SampleBankManager->m_AudioMixer->useAPDCM()) { data = (uint8*) realloc(data, sbh.SizeAdpcm[i]); sampleBank.seek(seekStart + sbh.OffsetAdpcm[i], CIFile::begin); sampleBank.serialBuffer(data, sbh.SizeAdpcm[i]); ibuffer->setFormat(IBuffer::FormatDviAdpcm, 1, 16, sbh.Freq[i]); if (!ibuffer->fill(data, sbh.SizeAdpcm[i])) nlwarning("AM: ibuffer->fill returned false with FormatADPCM"); } else { data = (uint8*) realloc(data, sbh.SizeMono16[i]); sampleBank.seek(seekStart + sbh.OffsetMono16[i], CIFile::begin); sampleBank.serialBuffer(data, sbh.SizeMono16[i]); ibuffer->setFormat(IBuffer::FormatPcm, 1, 16, sbh.Freq[i]); if (!ibuffer->fill(data, sbh.SizeMono16[i])) nlwarning("AM: ibuffer->fill returned false with FormatPCM"); } _ByteSize += ibuffer->getSize(); _Samples[nameId] = ibuffer; // Warn the sound bank that the sample are available. CAudioMixerUser::getInstance()->getSoundBank()->bufferLoaded(nameId, ibuffer); } free(data); _SampleBankManager->m_LoadedSize += _ByteSize; } catch(Exception &e) { // loading failed ! nlwarning("Exception %s during loading of sample bank %s", e.what(), filename.c_str()); if (_SampleBankManager->m_AudioMixer->getPackedSheetUpdate()) { nlinfo("Deleting offending sound bank, you need to restart to recreate it!"); CFile::deleteFile(filename); } } _Loaded = true; _LoadingDone = true; ///////////////////////////////////////// OLD Version ////////////////////////////////////// /* std::string list = CPath::lookup(CStringMapper::unmap(_Name)+CAudioMixerUser::SampleBankListExt, false); if (list.empty()) { nlwarning("File %s not found to load sample bank %s", (CStringMapper::unmap(_Name)+CAudioMixerUser::SampleBankListExt).c_str(), CStringMapper::unmap(_Name).c_str()); return; } NLMISC::CIFile sampleBankList(list); sampleBankList.serialCont(filenames); for (iter = filenames.begin(); iter != filenames.end(); iter++) { IBuffer* ibuffer = NULL; try { ibuffer = _SoundDriver->createBuffer(); nlassert(ibuffer); // std::string sampleName(CFile::getFilenameWithoutExtension(*iter)); NLMISC::TStringId sampleName(CStringMapper::map(CFile::getFilenameWithoutExtension(*iter))); if (async) { ibuffer->presetName(sampleName); nldebug("Preloading sample [%s]", CStringMapper::unmap(sampleName).c_str()); } else { std::string fullName = NLMISC::CPath::lookup(*iter, false); if (!fullName.empty()) { NLMISC::CIFile ifile(fullName); uint size = ifile.getFileSize(); uint8 *buffer = new uint8[ifile.getFileSize()]; ifile.serialBuffer(buffer, size); _SoundDriver->readWavBuffer(ibuffer, fullName, buffer, size); _ByteSize += ibuffer->getSize(); delete [] buffer; } } _Samples[sampleName] = ibuffer ; // Warn the sound bank that the sample are available. CSoundBank::instance()->bufferLoaded(sampleName, ibuffer); } catch (ESoundDriver &e) { if (ibuffer != NULL) { delete ibuffer; ibuffer = NULL; } nlwarning("Problem with file '%s': %s", (*iter).c_str(), e.what()); } } _Loaded = true; if (!async) { _LoadingDone = true; // compute the sample bank size. _LoadedSize += _ByteSize; } else { // fill the loading list. TSampleTable::iterator first(_Samples.begin()), last(_Samples.end()); for (; first != last; ++first) { _LoadList.push_back(make_pair(first->second, first->first)); } _SplitLoadDone = false; // send the first files for (uint i=0; i<ASYNC_LOADING_SPLIT && !_LoadList.empty(); ++i) { CAsyncFileManagerSound::getInstance().loadWavFile(_LoadList.front().first, CStringMapper::unmap(_LoadList.front().second)+".wav"); _LoadList.pop_front(); } // add a end loading event... CAsyncFileManagerSound::getInstance().signal(&_SplitLoadDone); // and register for update on the mixer CAudioMixerUser::instance()->registerUpdate(this); } */ }