| 326 | } |
| 327 | |
| 328 | void Voice::readAudioData(uint8_t* stream, int len) { |
| 329 | auto now = Time::monotonicMilliseconds(); |
| 330 | bool active = m_encoder && m_encodedChunksLength < 2048 |
| 331 | && (m_inputMode == VoiceInputMode::VoiceActivity || now < m_lastInputTime); |
| 332 | |
| 333 | size_t sampleCount = len / 2; |
| 334 | |
| 335 | if (active) { |
| 336 | float decibels = getAudioLoudness((int16_t*)stream, sampleCount); |
| 337 | |
| 338 | if (m_inputMode == VoiceInputMode::VoiceActivity) { |
| 339 | if (decibels > m_threshold) |
| 340 | m_lastThresholdTime = now; |
| 341 | active = now - m_lastThresholdTime < 50; |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | m_clientSpeaker->decibelLevel = getAudioLoudness((int16_t*)stream, sampleCount, m_inputAmplitude); |
| 346 | |
| 347 | if (!m_loopback) { |
| 348 | if (active && !m_clientSpeaker->playing) |
| 349 | m_clientSpeaker->lastPlayTime = now; |
| 350 | |
| 351 | m_clientSpeaker->playing = active; |
| 352 | } |
| 353 | |
| 354 | MutexLocker captureLock(m_captureMutex); |
| 355 | if (active) { |
| 356 | m_capturedChunksFrames += sampleCount / m_deviceChannels; |
| 357 | auto data = (opus_int16*)malloc(len); |
| 358 | memcpy(data, stream, len); |
| 359 | m_capturedChunks.emplace(data, sampleCount); // takes ownership |
| 360 | m_threadCond.signal(); |
| 361 | } |
| 362 | else { // Clear out any residual data so they don't manifest at the start of the next encode, whenever that is |
| 363 | while (!m_capturedChunks.empty()) |
| 364 | m_capturedChunks.pop(); |
| 365 | |
| 366 | m_capturedChunksFrames = 0; |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | void Voice::mix(int16_t* buffer, size_t frameCount, unsigned channels) { |
| 371 | size_t samples = frameCount * channels; |