Skip to content

Commit

Permalink
Returned callback system
Browse files Browse the repository at this point in the history
  • Loading branch information
emcifuntik committed Mar 22, 2023
1 parent fd1dd21 commit 1cc92a9
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 39 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/build-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ jobs:
copy build\windows\x64\release\alt-voice.lib upload\lib\release
copy build\windows\x64\debug\alt-voice.lib upload\lib\debug
copy include\alt-voice.h upload\include
copy include\IAudioFilter.h upload\include
copy include\IOpusDecoder.h upload\include
copy include\IOpusEncoder.h upload\include
copy include\ISoundIO.h upload\include
copy include\VoiceError.h upload\include
- uses: actions/upload-artifact@v3
with:
Expand Down Expand Up @@ -97,7 +102,7 @@ jobs:

- name: Zip artifacts
run: |
zip -r alt-voice-windows dist-windows/*
cd dist-windows && zip -r ../alt-voice-windows.zip .
# zip -r alt-voice-linux dist-linux/*

- name: Set outputs
Expand Down
27 changes: 10 additions & 17 deletions examples/devicetests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,9 @@ void ApplyFilter(void* buffer, uint32_t length)
RadioFilter->Process(buffer, length);
}

void AudioThread()
void AudioThread(void* buffer, uint32_t size)
{
for(;;)
{
if (soundInput)
{
int16_t buffer[FRAME_SIZE_BYTES / 10];
if (const auto len = soundInput->Read(buffer, FRAME_SIZE_BYTES / 10))
{
soundOutput->Write(buffer, len, ApplyFilter);
}
}
}
soundOutput->Write(buffer, size, ApplyFilter);
}

int main()
Expand All @@ -34,9 +24,9 @@ int main()

AltVoiceError filterCreateError = AV_CreateAudioFilter(&RadioFilter);

/*auto bqLowEffect = RadioFilter->ApplyBqfEffect(0, 1400, 0, 0.86f, 0, 0, 1);
auto bqLowEffect = RadioFilter->ApplyBqfEffect(0, 1400, 0, 0.86f, 0, 0, 1);
auto bqHighEffect = RadioFilter->ApplyBqfEffect(1, 900, 0, 0.83f, 0, 0, 2);
auto distortionEffect = RadioFilter->ApplyDistortionEffect(0.0f, -2.95f, -0.05f, -0.18f, 1.f, 3);*/
auto distortionEffect = RadioFilter->ApplyDistortionEffect(0.0f, -2.95f, -0.05f, -0.18f, 1.f, 3);

AV_CreateSoundOutput(64000, &soundOutput);

Expand All @@ -62,11 +52,14 @@ int main()
printf("%d: %s\n", i, soundInput->GetDeviceName(i));
}

soundInput->SetVolume(1.f);
soundInput->SetVolume(1.0f);
soundInput->SelectDevice(2);
soundInput->SetStreamEnabled(true);
soundInput->SetNoiseSuppressionEnabled(true);
soundInput->RegisterCallback(AudioThread);

std::thread audioThread(AudioThread);
audioThread.join();
for(;;)
{
Sleep(1000);
}
}
2 changes: 2 additions & 0 deletions include/ISoundIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class ISoundIO
virtual AltVoiceError SelectDevice(int id) = 0;
virtual int GetDevice() = 0;

virtual void RegisterCallback(OnVoiceCallback callback) {}

virtual void SetStreamEnabled(bool enabled) {}
virtual void SetNoiseSuppressionEnabled(const bool enabled) {}
};
64 changes: 46 additions & 18 deletions src/CSoundInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
#include <iostream>


CSoundInput::CSoundInput(int _bitRate) : encoder(new COpusEncoder(SAMPLE_RATE, AUDIO_CHANNELS, _bitRate))
CSoundInput::CSoundInput(int _bitRate) : encoder(new COpusEncoder(SAMPLE_RATE, AUDIO_CHANNELS, _bitRate)), bitrate(_bitRate)
{
denoiser = rnnoise_create(nullptr);
opusBuffer = new char[bitrate];
}

CSoundInput::~CSoundInput()
{
delete encoder;
delete opusBuffer;
rnnoise_destroy(denoiser);
BASS_RecordFree();
}
Expand All @@ -33,22 +35,7 @@ float CSoundInput::GetVolume()

int CSoundInput::Read(void* data, size_t size)
{
const int available = BASS_ChannelGetData(recordChannel, nullptr, BASS_DATA_AVAILABLE);
if (available < FRAME_SIZE_BYTES)
return 0;

int16_t inputData[FRAME_SIZE_SAMPLES];
if (BASS_ChannelGetData(recordChannel, inputData, FRAME_SIZE_BYTES) != FRAME_SIZE_BYTES)
return 0;

NoiseSuppressionProcess(inputData, FRAME_SIZE_SAMPLES);

const DWORD currentMicLevel = BASS_ChannelGetLevel(recordChannel);

const uint16_t leftChannelLevel = LOWORD(currentMicLevel);
micLevel = static_cast<float>(leftChannelLevel) / MaxShortFloatValue;

return encoder->EncodeShort(inputData, FRAME_SIZE_SAMPLES, data, size);
return 0;
}

float CSoundInput::GetLevel()
Expand Down Expand Up @@ -113,7 +100,8 @@ AltVoiceError CSoundInput::SelectDevice(int id)
if (!BASS_RecordInit(deviceId))
return AltVoiceError::DeviceInit;

recordChannel = BASS_RecordStart(SAMPLE_RATE, AUDIO_CHANNELS, 0, nullptr, this);
recordChannel = BASS_RecordStart(SAMPLE_RATE, AUDIO_CHANNELS, 0, OnSoundFrame, this);
BASS_ChannelSetAttribute(recordChannel, BASS_ATTRIB_GRANULE, FRAME_SIZE_SAMPLES);

// Change input volume
VolumeChangeFX = BASS_ChannelSetFX(recordChannel, BASS_FX_BFX_VOLUME, 0);
Expand All @@ -131,11 +119,27 @@ int CSoundInput::GetDevice()
return BASS_RecordGetDevice();
}

void CSoundInput::RegisterCallback(OnVoiceCallback callback)
{
VoiceCallback = callback;
}

void CSoundInput::SetNoiseSuppressionEnabled(const bool enabled)
{
noiseSuppressionEnabled = enabled;
}

BOOL CSoundInput::OnSoundFrame(HRECORD handle, const void* buffer, DWORD length, void* user)
{
const auto self = static_cast<CSoundInput*>(user);

for (int i = 0; i < length; i += (FRAME_SIZE_SAMPLES * sizeof(short)))
{
self->SoundFrameCaptured(handle, (char*)buffer + i, FRAME_SIZE_SAMPLES * sizeof(short));
}
return true;
}

void CSoundInput::NoiseSuppressionProcess(void* buffer, DWORD length)
{
if (noiseSuppressionEnabled)
Expand All @@ -161,3 +165,27 @@ void CSoundInput::NoiseSuppressionProcess(void* buffer, DWORD length)
}
}
}

void CSoundInput::SoundFrameCaptured(HRECORD handle, const void* buffer, DWORD length)
{
// Create new buffer on stack because buffer was marked as const in API
memcpy_s(writableBuffer, FRAME_SIZE_SAMPLES * sizeof(short), buffer, length);

// Apply noise suppression
NoiseSuppressionProcess(writableBuffer, FRAME_SIZE_SAMPLES);

// Get current microphone noise level
const DWORD currentMicLevel = BASS_ChannelGetLevel(handle);

// Get left channel noise level from it (because it's mono so right = left)
const uint16_t leftChannelLevel = LOWORD(currentMicLevel);

// Convert to float from 0.f to 1.f
micLevel = static_cast<float>(leftChannelLevel) / MaxShortFloatValue;

if (VoiceCallback)
{
const int opusBufferSize = encoder->EncodeShort(writableBuffer, FRAME_SIZE_SAMPLES, opusBuffer, bitrate);
VoiceCallback(opusBuffer, opusBufferSize);
}
}
11 changes: 10 additions & 1 deletion src/CSoundInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class CSoundInput : public ISoundIO

HRECORD recordChannel = 0;
COpusEncoder* encoder = nullptr;
int bitrate;

float volume = 1.f;
float micLevel = 0;
Expand All @@ -22,7 +23,11 @@ class CSoundInput : public ISoundIO
HFX VolumeChangeFX;
DenoiseState* denoiser;

short writableBuffer[FRAME_SIZE_SAMPLES];
float floatBuffer[FRAME_SIZE_SAMPLES];
char* opusBuffer = nullptr;

OnVoiceCallback VoiceCallback = nullptr;

public:
CSoundInput(int _bitRate);
Expand All @@ -41,8 +46,12 @@ class CSoundInput : public ISoundIO
AltVoiceError SelectDevice(int id) override;
int GetDevice() override;

void SetNoiseSuppressionEnabled(const bool enabled) override;
void RegisterCallback(OnVoiceCallback callback) override;

void SetNoiseSuppressionEnabled(const bool enabled) override;
void NoiseSuppressionProcess(void* buffer, DWORD length);
void SoundFrameCaptured(HRECORD handle, const void* buffer, DWORD length);

static BOOL OnSoundFrame(HRECORD handle, const void* buffer, DWORD length, void* user);
};

7 changes: 5 additions & 2 deletions src/CSoundOutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ void CSoundOutput::Write(void* data, size_t size, OnVoiceCallback filterCallback
int16_t outputBuffer[FRAME_SIZE_SAMPLES];
int len = decoder->DecodeShort(data, size, outputBuffer, FRAME_SIZE_SAMPLES, true, false);

filterCallback(outputBuffer, FRAME_SIZE_BYTES);
if (filterCallback)
{
filterCallback(outputBuffer, FRAME_SIZE_BYTES);
}

BASS_StreamPutData(outputStream, outputBuffer, FRAME_SIZE_BYTES);
}
Expand Down Expand Up @@ -70,7 +73,7 @@ AltVoiceError CSoundOutput::SelectDevice(int id)
}
}

if (!BASS_Init(deviceId, SAMPLE_RATE, 0, 0, nullptr))
if (!BASS_Init(deviceId, SAMPLE_RATE, 0, nullptr, nullptr))
{
if(BASS_ErrorGetCode() != BASS_ERROR_ALREADY)
return AltVoiceError::DeviceInit;
Expand Down

0 comments on commit 1cc92a9

Please sign in to comment.