forked from dolphin-emu/dolphin
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Credits to @degasus and @shuffle2 (godisgovernment): https://github.com/degasus/dolphin/tree/wiispeak
- Loading branch information
1 parent
c04460d
commit 0d7c985
Showing
17 changed files
with
828 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// Copyright 2024 Dolphin Emulator Project | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
|
||
#include "Core/IOS/USB/Emulated/Microphone.h" | ||
|
||
#include "Common/Swap.h" | ||
|
||
#include <algorithm> | ||
|
||
namespace IOS::HLE::USB | ||
{ | ||
std::vector<std::string> Microphone::ListDevices() | ||
{ | ||
std::vector<std::string> devices{}; | ||
const ALchar* pDeviceList = alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER); | ||
while (*pDeviceList) | ||
{ | ||
devices.emplace_back(pDeviceList); | ||
pDeviceList += strlen(pDeviceList) + 1; | ||
} | ||
|
||
return devices; | ||
} | ||
|
||
int Microphone::OpenMicrophone() | ||
{ | ||
m_device = alcCaptureOpenDevice(nullptr, SAMPLING_RATE, AL_FORMAT_MONO16, BUFFER_SIZE); | ||
m_dsp_data.resize(BUFFER_SIZE, 0); | ||
m_temp_buffer.resize(BUFFER_SIZE, 0); | ||
return static_cast<int>(alcGetError(m_device)); | ||
} | ||
|
||
int Microphone::StartCapture() | ||
{ | ||
alcCaptureStart(m_device); | ||
return static_cast<int>(alcGetError(m_device)); | ||
} | ||
|
||
void Microphone::StopCapture() | ||
{ | ||
alcCaptureStop(m_device); | ||
} | ||
|
||
void Microphone::PerformAudioCapture() | ||
{ | ||
m_num_of_samples = BUFFER_SIZE / 2; | ||
|
||
ALCint samples_in{}; | ||
alcGetIntegerv(m_device, ALC_CAPTURE_SAMPLES, 1, &samples_in); | ||
m_num_of_samples = std::min(m_num_of_samples, static_cast<u32>(samples_in)); | ||
|
||
if (m_num_of_samples == 0) | ||
return; | ||
|
||
alcCaptureSamples(m_device, m_dsp_data.data(), m_num_of_samples); | ||
} | ||
|
||
void Microphone::ByteSwap(const void* src, void* dst) const | ||
{ | ||
*static_cast<u16*>(dst) = Common::swap16(*static_cast<const u16*>(src)); | ||
} | ||
|
||
void Microphone::GetSoundData() | ||
{ | ||
if (m_num_of_samples == 0) | ||
return; | ||
|
||
u8* ptr = const_cast<u8*>(m_temp_buffer.data()); | ||
// Convert LE to BE | ||
for (u32 i = 0; i < m_num_of_samples; i++) | ||
{ | ||
for (u32 indchan = 0; indchan < 1; indchan++) | ||
{ | ||
const u32 curindex = (i * 2) + indchan * (16 / 8); | ||
ByteSwap(m_dsp_data.data() + curindex, ptr + curindex); | ||
} | ||
} | ||
|
||
m_rbuf_dsp.write_bytes(ptr, m_num_of_samples * 2); | ||
} | ||
|
||
void Microphone::ReadIntoBuffer(u8* dst, u32 size) | ||
{ | ||
m_rbuf_dsp.read_bytes(dst, size); | ||
} | ||
|
||
bool Microphone::HasData() const | ||
{ | ||
return m_num_of_samples != 0; | ||
} | ||
} // namespace IOS::HLE::USB |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Copyright 2024 Dolphin Emulator Project | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
|
||
#pragma once | ||
|
||
#include <OpenAL/al.h> | ||
#include <OpenAL/alc.h> | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
#include "Common/CommonTypes.h" | ||
|
||
namespace IOS::HLE::USB | ||
{ | ||
template <size_t S> | ||
class simple_ringbuf | ||
{ | ||
public: | ||
simple_ringbuf() { m_container.resize(S); } | ||
|
||
bool has_data() const { return m_used != 0; } | ||
|
||
u32 read_bytes(u8* buf, const u32 size) | ||
{ | ||
u32 to_read = size > m_used ? m_used : size; | ||
if (!to_read) | ||
return 0; | ||
|
||
u8* data = m_container.data(); | ||
u32 new_tail = m_tail + to_read; | ||
|
||
if (new_tail >= S) | ||
{ | ||
u32 first_chunk_size = S - m_tail; | ||
std::memcpy(buf, data + m_tail, first_chunk_size); | ||
std::memcpy(buf + first_chunk_size, data, to_read - first_chunk_size); | ||
m_tail = (new_tail - S); | ||
} | ||
else | ||
{ | ||
std::memcpy(buf, data + m_tail, to_read); | ||
m_tail = new_tail; | ||
} | ||
|
||
m_used -= to_read; | ||
|
||
return to_read; | ||
} | ||
|
||
void write_bytes(const u8* buf, const u32 size) | ||
{ | ||
if (u32 over_size = m_used + size; over_size > S) | ||
{ | ||
m_tail += (over_size - S); | ||
if (m_tail > S) | ||
m_tail -= S; | ||
|
||
m_used = S; | ||
} | ||
else | ||
{ | ||
m_used = over_size; | ||
} | ||
|
||
u8* data = m_container.data(); | ||
u32 new_head = m_head + size; | ||
|
||
if (new_head >= S) | ||
{ | ||
u32 first_chunk_size = S - m_head; | ||
std::memcpy(data + m_head, buf, first_chunk_size); | ||
std::memcpy(data, buf + first_chunk_size, size - first_chunk_size); | ||
m_head = (new_head - S); | ||
} | ||
else | ||
{ | ||
std::memcpy(data + m_head, buf, size); | ||
m_head = new_head; | ||
} | ||
} | ||
|
||
protected: | ||
std::vector<u8> m_container; | ||
u32 m_head = 0, m_tail = 0, m_used = 0; | ||
}; | ||
|
||
class Microphone final | ||
{ | ||
public: | ||
static std::vector<std::string> ListDevices(); | ||
|
||
int OpenMicrophone(); | ||
int StartCapture(); | ||
void StopCapture(); | ||
void PerformAudioCapture(); | ||
void GetSoundData(); | ||
void ReadIntoBuffer(u8* dst, u32 size); | ||
bool HasData() const; | ||
|
||
private: | ||
void ByteSwap(const void* src, void* dst) const; | ||
|
||
static constexpr u32 SAMPLING_RATE = 8000; | ||
static constexpr u32 BUFFER_SIZE = SAMPLING_RATE / 2; | ||
|
||
ALCdevice* m_device; | ||
u32 m_num_of_samples{}; | ||
std::vector<u8> m_dsp_data{}; | ||
std::vector<u8> m_temp_buffer{}; | ||
simple_ringbuf<BUFFER_SIZE> m_rbuf_dsp; | ||
}; | ||
} // namespace IOS::HLE::USB |
Oops, something went wrong.