// Main audio processing callback. // NOTE: Called on a separate thread from main() thread. ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow) { // Buffer size (in samples): long buffSize = drv.preferredSize; // Assume the buffer size is an even multiple of 32-bytes: assert((buffSize % sizeof(vec4_d64)) == 0); for (long i = 0; i < buffSize; ++i) { assert(index == 0 || index == 1); // Process 8 channels of 32-bit samples per iteration: for (long n = 0; n < inputChannels / 8; ++n) { const long ci = n * 8; const long co = drv.inputBuffers + ci; // Stripe input samples into a vector: const vec8_i32 inpSamples = _mm256_setr_epi32( ((long *)drv.bufferInfos[ci + 0].buffers[index])[i], ((long *)drv.bufferInfos[ci + 1].buffers[index])[i], ((long *)drv.bufferInfos[ci + 2].buffers[index])[i], ((long *)drv.bufferInfos[ci + 3].buffers[index])[i], ((long *)drv.bufferInfos[ci + 4].buffers[index])[i], ((long *)drv.bufferInfos[ci + 5].buffers[index])[i], ((long *)drv.bufferInfos[ci + 6].buffers[index])[i], ((long *)drv.bufferInfos[ci + 7].buffers[index])[i] ); // Process audio effects: vec8_i32 outSamples; processEffects(inpSamples, outSamples, n * 2); // Copy outputs to output channel buffers: const long *outputs32 = (const long *)&outSamples; ((long *)drv.bufferInfos[co + 0].buffers[index])[i] = outputs32[0]; ((long *)drv.bufferInfos[co + 1].buffers[index])[i] = outputs32[1]; ((long *)drv.bufferInfos[co + 2].buffers[index])[i] = outputs32[2]; ((long *)drv.bufferInfos[co + 3].buffers[index])[i] = outputs32[3]; ((long *)drv.bufferInfos[co + 4].buffers[index])[i] = outputs32[4]; ((long *)drv.bufferInfos[co + 5].buffers[index])[i] = outputs32[5]; ((long *)drv.bufferInfos[co + 6].buffers[index])[i] = outputs32[6]; ((long *)drv.bufferInfos[co + 7].buffers[index])[i] = outputs32[7]; } } if (drv.postOutput) ASIOOutputReady(); return 0L; }
void MageStats::recalculateDerivedStats() { clearDerivedStats(); processEffects(); mStrength += mStartingStrength + mBonusStrength + mSpentLevelsOnStrength; mMagic += mStartingMagic + mBonusMagic + mSpentLevelsOnMagic; mDexterity += mStartingDexterity + mBonusDexterity + mSpentLevelsOnDexterity; mVitality += mStartingVitality + mBonusVitality + mSpentLevelsOnVitality; mHP += mVitality + mBonusVitality + mLevel + 9; mMana += 2*mMagic + 2*mBonusMagic + 2*mLevel -2; mArmourClass += mDexterity/5; mDamageDoneBow += (mStrength * mLevel)/200; mDamageDoneMelee += (mStrength * mLevel)/100.0; mBlockingChance += mBlockingBonus; mBlockingChancePVP += mBlockingBonus; mBlockingChanceTrap += mDexterity + mBlockingBonus; mDamageDoneMelee += mPlayer->mInventory.getTotalAttackDamage(); mDamageDoneBow += mPlayer->mInventory.getTotalAttackDamage(); mArmourClass += mPlayer->mInventory.getTotalArmourClass(); mChanceToHitArrow += 10; }
void AudioPort::doProcessing() { if( m_mutedModel && m_mutedModel->value() ) { return; } const fpp_t fpp = Engine::mixer()->framesPerPeriod(); m_portBuffer = BufferManager::acquire(); // get buffer for processing Engine::mixer()->clearAudioBuffer( m_portBuffer, fpp ); // clear the audioport buffer so we can use it //qDebug( "Playhandles: %d", m_playHandles.size() ); foreach( PlayHandle * ph, m_playHandles ) // now we mix all playhandle buffers into the audioport buffer { if( ph->buffer() ) { if( ph->usesBuffer() ) { m_bufferUsage = true; MixHelpers::add( m_portBuffer, ph->buffer(), fpp ); } ph->releaseBuffer(); // gets rid of playhandle's buffer and sets // pointer to null, so if it doesn't get re-acquired we know to skip it next time } } if( m_bufferUsage ) { // handle volume and panning // has both vol and pan models if( m_volumeModel && m_panningModel ) { ValueBuffer * volBuf = m_volumeModel->valueBuffer(); ValueBuffer * panBuf = m_panningModel->valueBuffer(); // both vol and pan have s.ex.data: if( volBuf && panBuf ) { for( f_cnt_t f = 0; f < fpp; ++f ) { float v = volBuf->values()[ f ] * 0.01f; float p = panBuf->values()[ f ] * 0.01f; m_portBuffer[f][0] *= ( p <= 0 ? 1.0f : 1.0f - p ) * v; m_portBuffer[f][1] *= ( p >= 0 ? 1.0f : 1.0f + p ) * v; } } // only vol has s.ex.data: else if( volBuf ) { float p = m_panningModel->value() * 0.01f; float l = ( p <= 0 ? 1.0f : 1.0f - p ); float r = ( p >= 0 ? 1.0f : 1.0f + p ); for( f_cnt_t f = 0; f < fpp; ++f ) { float v = volBuf->values()[ f ] * 0.01f; m_portBuffer[f][0] *= v * l; m_portBuffer[f][1] *= v * r; } } // only pan has s.ex.data: else if( panBuf ) { float v = m_volumeModel->value() * 0.01f; for( f_cnt_t f = 0; f < fpp; ++f ) { float p = panBuf->values()[ f ] * 0.01f; m_portBuffer[f][0] *= ( p <= 0 ? 1.0f : 1.0f - p ) * v; m_portBuffer[f][1] *= ( p >= 0 ? 1.0f : 1.0f + p ) * v; } } // neither has s.ex.data: else { float p = m_panningModel->value() * 0.01f; float v = m_volumeModel->value() * 0.01f; for( f_cnt_t f = 0; f < fpp; ++f ) { m_portBuffer[f][0] *= ( p <= 0 ? 1.0f : 1.0f - p ) * v; m_portBuffer[f][1] *= ( p >= 0 ? 1.0f : 1.0f + p ) * v; } } } // has vol model only else if( m_volumeModel ) { ValueBuffer * volBuf = m_volumeModel->valueBuffer(); if( volBuf ) { for( f_cnt_t f = 0; f < fpp; ++f ) { float v = volBuf->values()[ f ] * 0.01f; m_portBuffer[f][0] *= v; m_portBuffer[f][1] *= v; } } else { float v = m_volumeModel->value() * 0.01f; for( f_cnt_t f = 0; f < fpp; ++f ) { m_portBuffer[f][0] *= v; m_portBuffer[f][1] *= v; } } } } // as of now there's no situation where we only have panning model but no volume model // if we have neither, we don't have to do anything here - just pass the audio as is // handle effects const bool me = processEffects(); if( me || m_bufferUsage ) { Engine::fxMixer()->mixToChannel( m_portBuffer, m_nextFxChannel ); // send output to fx mixer // TODO: improve the flow here - convert to pull model m_bufferUsage = false; } BufferManager::release( m_portBuffer ); // release buffer, we don't need it anymore }
// Main: int main() { int retval = 0; bool inited = false, buffersCreated = false, started = false; char *error = NULL; drv.sampleRate = 44100.0; // Initialize FX parameters: fx.f0_gain.init(); fx.f1_compressor.init(); // Set our own inputs: for (int i = 0; i < icr; ++i) { fx.f0_gain.input.gain[i] = _mm256_set1_pd(0); // dB fx.f1_compressor.input.threshold[i] = _mm256_set1_pd(-30); // dBFS fx.f1_compressor.input.attack[i] = _mm256_set1_pd(1.0); // msec fx.f1_compressor.input.release[i] = _mm256_set1_pd(80); // msec fx.f1_compressor.input.ratio[i] = _mm256_set1_pd(0.25); // N:1 fx.f1_compressor.input.gain[i] = _mm256_set1_pd(6); // dB } // Calculate input-dependent values: fx.f0_gain.recalc(); fx.f1_compressor.recalc(); // FX parameters are all set. #ifdef NOT_LIVE // Test mode: #if 0 const auto t0 = mm256_if_then_else(_mm256_cmp_pd(_mm256_set1_pd(-1.0), _mm256_set1_pd(0.0), _CMP_LT_OQ), _mm256_set1_pd(0.0), _mm256_set1_pd(-1.0)); printvec_dB(t0); printf("\n\n"); const auto p0 = mm256_if_then_else(_mm256_cmp_pd(_mm256_set1_pd(-1.0), _mm256_set1_pd(0.0), _CMP_LT_OQ), _mm256_set1_pd(0.0), _mm256_set1_pd(1.0)); printvec_dB(t0); printf("\n\n"); const auto t1 = mm256_if_then_else(_mm256_cmp_pd(_mm256_set1_pd(0.0), _mm256_set1_pd(0.0), _CMP_LT_OQ), _mm256_set1_pd(0.0), _mm256_set1_pd(-1.0)); printvec_dB(t1); printf("\n\n"); const auto p1 = mm256_if_then_else(_mm256_cmp_pd(_mm256_set1_pd(0.0), _mm256_set1_pd(0.0), _CMP_LT_OQ), _mm256_set1_pd(0.0), _mm256_set1_pd(1.0)); printvec_dB(t1); printf("\n\n"); goto done; #endif vec8_i32 in, out; long long c = 0LL; for (int i = 0; i < 20; ++i) { for (int n = 0; n < 48; ++n, ++c) { double s = sin(2.0 * 3.14159265358979323846 * (double)c / drv.sampleRate); int si = (int)(s * INT_MAX / 2); in = _mm256_set1_epi32(si); processEffects(in, out, 0); } #if 1 printf("samp: "); printvec_samp(in); printf("\n"); printf("input: "); for (int n = 0; n < icr; ++n) { printvec_dB(fx.fi_monitor.levels[n]); if (n < icr - 1) printf(" "); } printf("\n"); printf("gain: "); for (int n = 0; n < icr; ++n) { printvec_dB(fx.f0_output.levels[n]); if (n < icr - 1) printf(" "); } printf("\n"); printf("comp: "); for (int n = 0; n < icr; ++n) { printvec_dB(fx.fo_monitor.levels[n]); if (n < icr - 1) printf(" "); } printf("\n"); printf("samp: "); printvec_samp(out); printf("\n\n"); #endif } #else // ASIO live engine mode: if (!loadAsioDriver("UA-1000")) { error = "load failed."; goto err; } if (ASIOInit(&drv.driver) != ASE_OK) goto err; inited = true; if (ASIOGetChannels(&drv.inputChannels, &drv.outputChannels) != ASE_OK) goto err; printf("in: %d, out %d\n", drv.inputChannels, drv.outputChannels); if (ASIOGetBufferSize(&drv.minSize, &drv.maxSize, &drv.preferredSize, &drv.granularity) != ASE_OK) goto err; printf("min buf size: %d, preferred: %d, max buf size: %d\n", drv.minSize, drv.preferredSize, drv.maxSize); if (ASIOGetSampleRate(&drv.sampleRate) != ASE_OK) goto err; printf("rate: %f\n\n", drv.sampleRate); if (ASIOOutputReady() == ASE_OK) drv.postOutput = true; else drv.postOutput = false; // fill the bufferInfos from the start without a gap ASIOBufferInfo *info = drv.bufferInfos; // prepare inputs (Though this is not necessarily required, no opened inputs will work, too if (drv.inputChannels > kMaxInputChannels) drv.inputBuffers = kMaxInputChannels; else drv.inputBuffers = drv.inputChannels; for (int i = 0; i < drv.inputBuffers; i++, info++) { info->isInput = ASIOTrue; info->channelNum = i; info->buffers[0] = info->buffers[1] = 0; } // prepare outputs if (drv.outputChannels > kMaxOutputChannels) drv.outputBuffers = kMaxOutputChannels; else drv.outputBuffers = drv.outputChannels; for (int i = 0; i < drv.outputBuffers; i++, info++) { info->isInput = ASIOFalse; info->channelNum = i; info->buffers[0] = info->buffers[1] = 0; } asioCallbacks.asioMessage = asioMessage; asioCallbacks.bufferSwitch = bufferSwitch; asioCallbacks.bufferSwitchTimeInfo = bufferSwitchTimeInfo; // Create the buffers: if (ASIOCreateBuffers(drv.bufferInfos, drv.inputBuffers + drv.outputBuffers, drv.preferredSize, &asioCallbacks) != ASE_OK) goto err; else buffersCreated = true; // now get all the buffer details, sample word length, name, word clock group and activation for (int i = 0; i < drv.inputBuffers + drv.outputBuffers; i++) { drv.channelInfos[i].channel = drv.bufferInfos[i].channelNum; drv.channelInfos[i].isInput = drv.bufferInfos[i].isInput; if (ASIOGetChannelInfo(&drv.channelInfos[i]) != ASE_OK) goto err; //printf("%s[%2d].type = %d\n", drv.channelInfos[i].isInput ? "in " : "out", drv.channelInfos[i].channel, drv.channelInfos[i].type); if (drv.channelInfos[i].type != ASIOSTInt32LSB) { error = "Application assumes sample types of ASIOSTInt32LSB!"; goto err; } } // get the input and output latencies // Latencies often are only valid after ASIOCreateBuffers() // (input latency is the age of the first sample in the currently returned audio block) // (output latency is the time the first sample in the currently returned audio block requires to get to the output) if (ASIOGetLatencies(&drv.inputLatency, &drv.outputLatency) != ASE_OK) goto err; printf ("latencies: input: %d, output: %d\n", drv.inputLatency, drv.outputLatency); // Start the engine: if (ASIOStart() != ASE_OK) goto err; else started = true; printf("Engine started.\n\n"); const int total_time = 30; for (int i = 0; i < total_time; ++i) { printf("Engine running %2d. \r", total_time - i); Sleep(1000); } #endif goto done; err: if (error == NULL) error = drv.driver.errorMessage; if (error != NULL) fprintf(stderr, "%s\r\n", error); retval = -1; done: if (started) ASIOStop(); if (buffersCreated) ASIODisposeBuffers(); if (inited) ASIOExit(); return retval; }
void LevelScene::update() { if(m_luaEngine.shouldShutdown()) { m_fader.setFade(10, 1.0, 1.0); setExiting(0, LvlExit::EXIT_Error); } Scene::update(); if(!m_isPauseMenu) tickAnimations(uTickf); if(!m_isLevelContinues) { //Level exit timeout m_exitLevelDelay -= uTickf; if(m_exitLevelDelay <= 0.0) { m_doExit = true; if(m_fader.isNull()) { if(PGE_MusPlayer::isPlaying()) PGE_MusPlayer::fadeOut(500); m_fader.setFade(10, 1.0, 0.01); } } } if(m_doExit) { if(m_exitLevelCode == LvlExit::EXIT_Closed) { m_fader.setFull(); m_isRunning = false; } else { if(m_fader.isFull()) m_isRunning = false; } } else if(m_isPauseMenu) processPauseMenu(); else { //Update physics is not pause menu updateLua();//Process LUA code m_systemEvents.processEvents(uTickf); m_events.processTimers(uTickf); //update cameras for(PGE_LevelCamera &cam : m_cameras) cam.updatePre(uTickf); processEffects(uTickf); if(!m_isTimeStopped) //if activated Time stop bonus or time disabled by special event { //Make world step processPhysics(uTickf); } while(!m_blockTransforms.empty()) { transformTask_block x = m_blockTransforms.front(); x.block->transformTo_x(x.id); m_blockTransforms.pop_front(); } // Send controller states to controllable objects m_player1Controller->sendControls(); m_player2Controller->sendControls(); //update players for(LVL_Player *plr : m_itemsPlayers) { plr->update(uTickf); if(PGE_Window::showDebugInfo) { m_debug_player_jumping = plr->m_jumpPressed; m_debug_player_onground = plr->onGround(); m_debug_player_foots = (int)plr->l_contactB.size(); } } for(size_t i = 0; i < m_blocksInFade.size(); i++) { if(m_blocksInFade[i]->tickFader(uTickf)) { m_blocksInFade.erase(m_blocksInFade.begin() + (int)i); i--; } } //Process activated NPCs //for(size_t i = 0; i < m_npcActive.size(); i++) for(auto i = m_npcActive.begin(); i != m_npcActive.end();) { LVL_Npc *n = *i; n->update(uTickf); if(n->isKilled()) { i = m_npcActive.erase(i); continue; } else if(n->activationTimeout <= 0) { if(!n->warpSpawing) n->deActivate(); if(n->wasDeactivated) { if(!isVizibleOnScreen(n->m_momentum) || !n->isVisible() || !n->is_activity) { n->wasDeactivated = false; i = m_npcActive.erase(i); continue; } } } ++i; } if(!m_isTimeStopped) //if activated Time stop bonus or time disabled by special event { //Process and resolve collisions processAllCollisions(); } /***************Collect garbage****************/ if(!m_npcDead.empty()) collectGarbageNPCs(); if(!m_playersDead.empty()) collectGarbagePlayers(); if(!m_blocksToDelete.empty()) collectGarbageBlocks(); /**********************************************/ //update cameras for(PGE_LevelCamera &cam : m_cameras) { cam.updatePost(uTickf); //! --------------DRAW HUD-------------------------------------- // TODO: Implement separated render queue for elements of HUD and provide render functions // are will draw HUD elements after world has drawn. LuaEngine *sceneLuaEngine = getLuaEngine(); if(sceneLuaEngine) { if(sceneLuaEngine->isValid() && !sceneLuaEngine->shouldShutdown()) { LuaEvent drawHUDEvent = BindingCore_Events_Engine::createDrawLevelHUDEvent(sceneLuaEngine, &cam, &m_playerStates[(size_t)(cam.playerID - 1)]); sceneLuaEngine->dispatchEvent(drawHUDEvent); } } //! ------------------------------------------------------------ } //Add effects into the render table for(Scene_Effect &item : WorkingEffects) { renderArrayAddFunction([&item](double camPosX, double camPosY) { item.render(camPosX, camPosY); }, item.m_zIndex); } //Clear garbage (be careful!) //luaEngine.runGarbageCollector(); } //Process interprocessing commands cache process_InterprocessCommands(); //Process Z-sort of the render functions renderArrayPrepare(); //Process message boxes m_messages.process(); }
/* Read the entire message from js, then take action. * Thus messages will remain in sync. */ static int readMessage(void) { int l; char *msg; /* error message from js */ if (readFromJS(&head, sizeof(head)) < 0) return -1; /* read failed */ if (head.magic != EJ_MAGIC) { /* this should never happen */ js_kill(); i_puts(MSG_JSEngineSync); markAllDead(); return -1; } if (head.highstat >= EJ_HIGH_HEAP_FAIL) { js_kill(); /* perhaps a helpful message, before we close down js sessions */ if (head.highstat == EJ_HIGH_PROC_FAIL) allowJS = false; if (head.lowstat == EJ_LOW_EXEC) i_puts(MSG_JSEngineExec); if (head.lowstat == EJ_LOW_MEMORY) i_puts(MSG_JavaMemError); if (head.lowstat == EJ_LOW_RUNTIME) i_puts(MSG_JSEngineRun); if (head.lowstat == EJ_LOW_SYNC) i_puts(MSG_JSEngineSync); markAllDead(); return -1; } if (head.side) { effects = allocMem(head.side + 1); if (readFromJS(effects, head.side) < 0) { free(effects); effects = 0; return -1; } effects[head.side] = 0; // because debugPrint always puts on a newline effects[head.side - 1] = 0; debugPrint(4, "< side effects\n%s", effects); processEffects(); } /* next grab the error message, if there is one */ l = head.msglen; if (l) { msg = allocMem(l + 1); if (readFromJS(msg, l)) { free(msg); return -1; } msg[l] = 0; if (debugLevel >= 3) { /* print message, this will be in English, and mostly for our debugging */ if (jsSourceFile) { if (debugFile) fprintf(debugFile, "%s line %d: ", jsSourceFile, head.lineno); else printf("%s line %d: ", jsSourceFile, head.lineno); } debugPrint(3, "%s", msg); } free(msg); } /* Read in the requested property, if there is one. * The calling function must handle the property. */ l = head.proplength; proptype = head.proptype; if (l) { propval = allocMem(l + 1); if (readFromJS(propval, l)) { free(propval); propval = 0; return -1; } propval[l] = 0; } /* stop at the first js error when debugging */ if (head.msglen && debugLevel >= 5) { head.highstat = EJ_HIGH_CX_FAIL; head.lowstat = 0; debugPrint(5, "js abort due to error while debugging"); } if (head.highstat == EJ_HIGH_CX_FAIL) { if (head.lowstat == EJ_LOW_VARS) i_puts(MSG_JSEngineVars); if (head.lowstat == EJ_LOW_CX) i_puts(MSG_JavaContextError); if (head.lowstat == EJ_LOW_WIN) i_puts(MSG_JavaWindowError); if (head.lowstat == EJ_LOW_DOC) i_puts(MSG_JavaObjError); if (head.lowstat == EJ_LOW_CLOSE) i_puts(MSG_PageDone); else i_puts(MSG_JSSessionFail); freeJavaContext(cw); /* should I free and zero the property at this point? */ } return 0; } /* readMessage */