IsInGameThread Exception thrown

444_Nuits
Tue, 16 Apr 2024 09:15:06 +0000
Programming & Scripting

Hii,
I’m trying to convert an audio signal using threads here’s how it works :

I have an Actor named AAudioActor and when I press the vKey, I call the start imitation Function of it :

void AAudioCaptureActor::StartImitation()
{
  if (_bIsRunning)
    return;

  _bIsRunning = true;
  _thread = FRunnableThread::Create(new AudioProcessorWorker(this), TEXT("AudioProcessorWorker"), 0, TPri_Highest);
}

As you see, it instantiates a worker inheriting from FRunnable :

class AudioProcessorWorker : public FRunnable
{
private:
	AAudioCaptureActor* _instance;

public:
	AudioProcessorWorker(AAudioCaptureActor* instance) : _instance(instance){}

	virtual ~AudioProcessorWorker() {
		if (_instance->_thread)
			_instance->_thread->Kill();
		delete _instance->_thread;
	}

	virtual bool Init() override { return true; }
	virtual void Stop() override { _instance->_bIsRunning = false; }
	virtual void Exit() override {}

	virtual uint32 Run() override
	{
		UE_LOG(LogTemp, Warning, TEXT("AudioProcessorWorker::BeforeLoop"));
		while (_instance->_bIsRunning)
		{
			FAudioData AudioData;
			AudioData.Samples =_instance->CaptureAudioData();
			if (_instance->AudioDataQueue.Dequeue(AudioData))
			{
				UE_LOG(LogTemp, Warning, TEXT("AudioProcessorWorker::DataDetected"));
				// Process audio data
				_instance->ProcessAudioData(AudioData.Samples);
			}
			FPlatformProcess::Sleep(0.01f); // Adjust sleep duration as needed
			UE_LOG(LogTemp, Warning, TEXT("AudioProcessorWorker::InLoop"));
			_instance->PlayAudioData(AudioData.Samples);
		}
		UE_LOG(LogTemp, Warning, TEXT("AudioProcessorWorker::AfterLoop"));
		return 0;
	}
};

My issue occurs in the Run() function of my thread, when I call the CaptureAudioData function of my actor :

std::vector<int16> AAudioCaptureActor::CaptureAudioData()
{

  UClass* AudioCaptureComponentClass = UMyCaptureComponent::StaticClass();
  UMyCaptureComponent* AudioCapture = Cast<UMyCaptureComponent>(AddComponentByClass(AudioCaptureComponentClass, false, FTransform::Identity, false));

  // Initialize variables for audio capture
  float SampleRate = 32000.0f;
  float NumChannels = 2; // Assuming stereo audio
  const int32 NumSamplesPerFrame = 320; // 10 ms per frame at 32 kHz sample rate

  //// Assign a submix and start capturing audio
  USoundSubmix* Submix = NewObject<USoundSubmix>();
  AudioCapture->SoundSubmix = Submix;
  AudioCapture->Start();

  // Start recording
  Audio::FMixerDevice* MixerDevice = FAudioDeviceManager::GetAudioMixerDeviceFromWorldContext(GetWorld());
  MixerDevice->RegisterSoundSubmix(Submix);
  MixerDevice->StartRecording(Submix, 0);

  // Mute echo
  Submix->SetSubmixOutputVolume(GetWorld(), 0);

  // Stop recording audio
  Audio::FAlignedFloatBuffer Buffer = MixerDevice->StopRecording(Submix, NumChannels, SampleRate);

  // Convert captured audio data to int16 format
  std::vector<int16> InputAudio;
  InputAudio.reserve(Buffer.Num() / NumChannels);
  for (float Sample : Buffer)
  {
    // Scale floating-point sample to int16 range
    int16 ScaledSample = static_cast<int16>(Sample);
    InputAudio.push_back(ScaledSample);
  }
  return InputAudio;
}

This line:

Audio::FMixerDevice* MixerDevice = FAudioDeviceManager::GetAudioMixerDeviceFromWorldContext(GetWorld());

tells me that the current thread I’m trying to use an Unreal’s function without being in the game thread could anyone suggest me on how I could fix my code to work in the game thread ?

8 posts - 3 participants