공부중

[UE] 마이크로 전달한 음성 데이터를 wav파일로 저장해보자. - 2 본문

Programing/UnrealEngine

[UE] 마이크로 전달한 음성 데이터를 wav파일로 저장해보자. - 2

곤란 2024. 7. 16. 15:15
반응형

https://hannom.tistory.com/237

 

[UE] 마이크로 전달한 음성 데이터를 wav파일로 저장해보자. - 1

들어가기전 잡담을 좀 하자면 6월초에 수술을 받고 6월 내내 누워 지내다가 이제서야 어느정도 회복이 되어서 앉을수 있게 되었다 하하하하하하 건강챙기자.. -_-...이전 회사에서 했던 작업중 마

hannom.tistory.com

이전글에서 이어서 위젯을 만들고 실제로 녹음까지 해보도록 하자.

 

UserWidget을 상속받는 클래스를 만들어준다. 이름은 VoiceRecordWidget으로 지었다.

일단 코드는 이후에 작성해 주도록 하고 앞에서 만든 VoiceRecordWidget을 상속받는 위젯 블루프린트를 만들어 준다.

이름은 WBP_VoiceRecordWidget으로 지어주었다.

적당히 위젯 디자인을 해준다.

간단하게 테스트 할것이고 RecordStart / RecordStop 두개의 버튼을 WidgetSwitcher를 통해서 변경하도록 할 것이다.

이제 코드를 작성해보도록 하자.

class UVoiceRecordComponent;

class UButton;
class UWidgetSwitcher;

UCLASS()
class VOICERECORDPROJ_API UVoiceRecordWidget : public UUserWidget
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintCallable, Category = "VoiceRecord")
	void			RecordStart();

	UFUNCTION(BlueprintCallable, Category = "VoiceRecord")
	void			RecordStop();

public:
	UFUNCTION()
	void			OnClicked_RecordStart();

	UFUNCTION()
	void			OnClicked_RecordStop();

	UFUNCTION()
	void			OnStartVoiceRecord();

	UFUNCTION()
	void			OnStopVoiceRecord();
public:
	UFUNCTION(BlueprintCallable, Category = "VoiceRecordWidget")
	void			SetVoiceRecordComponent(UVoiceRecordComponent* VoiceRecordComponent);
    
    UFUNCTION(BlueprintCallable, Category = "VoiceRecordWidget")
	void			ResetVoiceRecordComponent();

protected:
	virtual void		NativeConstruct() override;
	virtual void		NativeDestruct() override;

protected:
	TWeakObjectPtr<UVoiceRecordComponent>	_VoiceRecordComponent = nullptr;

protected:
	UPROPERTY(BlueprintReadOnly, meta = (BindWidget))
	TObjectPtr<UButton>					Button_RecordStart;

	UPROPERTY(BlueprintReadOnly, meta = (BindWidget))
	TObjectPtr<UButton>					Button_RecordStop;

	UPROPERTY(BlueprintReadOnly, meta = (BindWidget))
	TObjectPtr<UWidgetSwitcher>			WidgetSwitcher_RecordButtons;

};

위젯이 바인드 되었는지 확인하고 버튼 클릭 이벤트 바인딩/언바인딩 모두 NativeConstruct와 NativeDestruct에서 해줄 예정이다.

이제 CPP코드를 보자.

#include "UMG/VoiceRecordWidget.h"
#include "Components/Button.h"
#include "Components/WidgetSwitcher.h"
#include "Component/VoiceRecordComponent.h"

void UVoiceRecordWidget::RecordStart()
{
	if (_VoiceRecordComponent.IsValid())
	{
		_VoiceRecordComponent->StartRecord();
	}
}

void UVoiceRecordWidget::RecordStop()
{
	if (_VoiceRecordComponent.IsValid())
	{
		_VoiceRecordComponent->StopRecord();
	}
}

void UVoiceRecordWidget::OnClicked_RecordStart()
{
	RecordStart();
}

void UVoiceRecordWidget::OnClicked_RecordStop()
{
	RecordStop();
}

버튼 클릭시 OnClicked_ 접두가 붙은 RecordStart와 RecordStop을 호출 하도록 할 예정이다.

void UVoiceRecordWidget::OnStartVoiceRecord()
{
	if (WidgetSwitcher_RecordButtons)
	{
		WidgetSwitcher_RecordButtons->SetActiveWidget(Button_RecordStop);
	}
}

void UVoiceRecordWidget::OnStopVoiceRecord()
{
	if (WidgetSwitcher_RecordButtons)
	{
		WidgetSwitcher_RecordButtons->SetActiveWidget(Button_RecordStop);
	}
}

void UVoiceRecordWidget::SetVoiceRecordComponent(UVoiceRecordComponent* VoiceRecordComponent)
{
	if (!VoiceRecordComponent)
	{
		return;
	}

	_VoiceRecordComponent = VoiceRecordComponent;

	_VoiceRecordComponent->GetOnStartVoiceRecord().AddDynamic(this, &UVoiceRecordWidget::OnStartVoiceRecord);
	_VoiceRecordComponent->GetOnStopVoiceRecord().AddDynamic(this, &UVoiceRecordWidget::OnStopVoiceRecord);
}

void UVoiceRecordWidget::ResetVoiceRecordComponent()
{
	if (_VoiceRecordComponent.IsValid())
	{
		_VoiceRecordComponent->GetOnStartVoiceRecord().RemoveDynamic(this, &UVoiceRecordWidget::OnStartVoiceRecord);
		_VoiceRecordComponent->GetOnStopVoiceRecord().RemoveDynamic(this, &UVoiceRecordWidget::OnStopVoiceRecord);

		_VoiceRecordComponent = nullptr;
	}
}

VoiceRecordComponent에서 Record 시작/정지 일때 호출된 델리게이트에 따라서 WidgetSwitch로 보여줄 위젯을 바꾸도록 한다.

그리고 VoiceRecordComponent의 Delegate에 Bind / UnBind 하는 코드도 작성한다.

void UVoiceRecordWidget::NativeConstruct()
{
	if (Button_RecordStart)
	{
		Button_RecordStart->OnClicked.AddDynamic(this, &UVoiceRecordWidget::OnClicked_RecordStart);
	}

	if (Button_RecordStop)
	{
		Button_RecordStop->OnClicked.AddDynamic(this, &UVoiceRecordWidget::OnClicked_RecordStop);
	}
}

void UVoiceRecordWidget::NativeDestruct()
{
	if (Button_RecordStart)
	{
		Button_RecordStart->OnClicked.RemoveDynamic(this, &UVoiceRecordWidget::OnClicked_RecordStart);
	}

	if (Button_RecordStop)
	{
		Button_RecordStop->OnClicked.RemoveDynamic(this, &UVoiceRecordWidget::OnClicked_RecordStop);
	}

	ResetVoiceRecordComponent();
}

Construct / Destruct에서 Button OnCliecked 이벤트에 바인딩 해준다.

이제 위젯을 생성하고 Viewport에 추가해보자. 간단하게 작업하기 위해서 Blueprint로 호다닥 작업해주었다.

이전에 만들었던 BP_RecordActor를 열어준다.

WBP_VoiceRecordWidget을 생성하고 위젯에서 SetVoiceRecordComponent를 통해서 BP_RecordActor에 Component를 넘겨준다 그리고 Add To Viewport를 호출해주었다.

 

이제 실행해서 제데로 녹음 되는지 확인해 보자.

https://youtu.be/5eNIfSTdrik

RecordRecv의 출력볼륨과 웻레벨을 최솟값 -96.0으로 설정해서 마이크로 말하는 내용이 들리지 않는다.

코드에서 작성한 대로 saved 폴더 안에 들어가면 RecordVoiceFile.wav파일이 생성된것을 확인 할 수 있다.

https://www.youtube.com/watch?v=unomY6FCuB8

재생해 보면 음성 녹음 된것을 확인 가능하다.

 

반응형