12-25-2025, 02:27 AM
I think my mic is broken or something so can someone test this please...
Microphone.h
ANd the QB64 stuff
@Petr 90% there i reckon...needs a better brain!
Unseeen
Microphone.h
Code: (Select All)
#ifndef QBLIVE_AUDIO_H
#define QBLIVE_AUDIO_H
#include <windows.h>
#include <mmsystem.h>
#include <shellapi.h>
#include <vector>
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "shell32.lib")
#define SAMPLE_RATE 44100
#define CHUNK_SIZE 4096
static HWAVEIN hWaveIn = NULL;
static HWAVEOUT hWaveOut = NULL;
static WAVEHDR waveHdrIn;
static short captureBuffer[CHUNK_SIZE];
static std::vector<short> recordedData;
static bool isRecording = false;
// Driver Callback: Background thread catches audio chunks as they arrive
void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
if (uMsg == WIM_DATA && isRecording) {
WAVEHDR* pHdr = (WAVEHDR*)dwParam1;
short* raw = (short*)pHdr->lpData;
// Efficiently append raw 16-bit samples to the storage vector
recordedData.insert(recordedData.end(), raw, raw + (pHdr->dwBytesRecorded / 2));
// Re-queue the buffer to keep recording without gaps
waveInAddBuffer(hwi, pHdr, sizeof(WAVEHDR));
}
}
extern "C" {
__declspec(dllexport) int InitAudio() {
// CD Quality: Mono, 44100Hz, 16-bit PCM
WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, SAMPLE_RATE, SAMPLE_RATE * 2, 2, 16, 0 };
// Open Microphone
MMRESULT res = waveInOpen(&hWaveIn, WAVE_MAPPER, &wfx, (DWORD_PTR)waveInProc, 0, CALLBACK_FUNCTION);
if (res != MMSYSERR_NOERROR) return (int)res;
waveHdrIn.lpData = (LPSTR)captureBuffer;
waveHdrIn.dwBufferLength = CHUNK_SIZE * 2;
waveHdrIn.dwFlags = 0;
waveInPrepareHeader(hWaveIn, &waveHdrIn, sizeof(WAVEHDR));
// Open Speakers
if (waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) return -99;
return 0;
}
__declspec(dllexport) void StartRecord() {
recordedData.clear();
isRecording = true;
waveInAddBuffer(hWaveIn, &waveHdrIn, sizeof(WAVEHDR));
waveInStart(hWaveIn);
}
__declspec(dllexport) void StopRecord() {
isRecording = false;
waveInStop(hWaveIn);
waveInReset(hWaveIn);
}
__declspec(dllexport) int GetRecordedSize() {
return (int)recordedData.size();
}
__declspec(dllexport) void PlayRecording() {
if (recordedData.empty()) return;
static WAVEHDR playHdr; // Static ensures memory persists during playback
playHdr.lpData = (LPSTR)recordedData.data();
playHdr.dwBufferLength = (DWORD)recordedData.size() * 2;
playHdr.dwFlags = 0;
waveOutPrepareHeader(hWaveOut, &playHdr, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, &playHdr, sizeof(WAVEHDR));
}
__declspec(dllexport) void OpenMicSettings() {
ShellExecuteA(NULL, "open", "ms-settings:privacy-microphone", NULL, NULL, SW_SHOWNORMAL);
}
__declspec(dllexport) void ShutdownAudio() {
if (hWaveIn) { waveInReset(hWaveIn); waveInClose(hWaveIn); }
if (hWaveOut) { waveOutReset(hWaveOut); waveOutClose(hWaveOut); }
}
// Converts 16-bit samples to 32-bit floats for QB64 _SNDRAW
// buffer = the QB64 float array, offset = starting sample, count = samples to get
__declspec(dllexport) void Audio_Get_SndRaw(float* buffer, int offset, int count) {
if (recordedData.empty() || offset < 0) return;
for (int i = 0; i < count; i++) {
int index = offset + i;
if (index < (int)recordedData.size()) {
// Convert signed 16-bit (-32768 to 32767) to float (-1.0 to 1.0)
buffer[i] = (float)recordedData[index] / 32768.0f;
} else {
buffer[i] = 0.0f; // Fill remaining buffer with silence if out of range
}
}
}
}
#endif
ANd the QB64 stuff
Code: (Select All)
' Finalized QBLive Audio Studio 2025
DECLARE LIBRARY "Microphone"
FUNCTION InitAudio& ()
SUB StartRecord ()
SUB StopRecord ()
FUNCTION GetRecordedSize& ()
SUB PlayRecording ()
SUB OpenMicSettings ()
SUB ShutdownAudio ()
SUB Audio_Get_SndRaw (buffer AS SINGLE, BYVAL offset AS LONG, BYVAL count AS LONG)
END DECLARE
SCREEN _NEWIMAGE(800, 600, 32)
_TITLE "QBLive Audio Recorder 2025"
' 1. Check Permissions
res& = InitAudio
IF res& <> 0 THEN
PRINT "--- AUDIO INITIALIZATION ERROR ---"
PRINT "Result Code:"; res&
PRINT "Hardware not found or Privacy Permissions denied."
PRINT
INPUT "Open Windows Microphone Settings? (Y/N) ", c$
IF UCASE$(c$) = "Y" THEN OpenMicSettings
END
END IF
isRecording = 0
PRINT "Ready. Press SPACE to Record."
DO
k$ = INKEY$
IF k$ = " " THEN
IF isRecording = 0 THEN
StartRecord
isRecording = 1
ELSE
StopRecord
isRecording = 0
CLS
PRINT "Playing back"; GetRecordedSize; "samples..."
'PlayRecording ''// This maybe the error
samples& = GetRecordedSize
IF samples& > 0 THEN
PRINT "Playing back via _SNDRAW..."
' We process in chunks of 4096 (matching your C++ CHUNK_SIZE)
chunkSize& = 4096
REDIM tempBuffer(chunkSize& - 1) AS SINGLE
FOR currentOffset& = 0 TO samples& STEP chunkSize&
' 1. Fill our QB64 float buffer from the C++ recordedData vector
Audio_Get_SndRaw tempBuffer(0), currentOffset&, chunkSize&
' 2. Call our standalone sub to handle the actual playback
PlayFloatBuffer tempBuffer(), chunkSize&
NEXT currentOffset&
PRINT "Playback finished."
END IF
PRINT "Press SPACE to record again."
END IF
_DELAY .3 ' Toggle debounce
END IF
IF isRecording THEN
LOCATE 1, 1: PRINT "RECORDING... ["; GetRecordedSize; "samples]"
END IF
_LIMIT 60
LOOP UNTIL _EXIT
ShutdownAudio
SYSTEM
SUB PlayFloatBuffer (floatArray() AS SINGLE, count AS LONG)
' Designed for 44100Hz Mono Audio
IF count <= 0 THEN EXIT SUB
FOR i& = 0 TO count - 1
' 1. Send the sample to _SNDRAW (mono automatically goes to both speakers)
_SNDRAW floatArray(i&)
' 2. Check the sound pipe length.
' If we queue too much data (> 0.2 seconds), we wait.
' If we don't wait, QB64 will eat up all your RAM trying to store the samples.
IF i& MOD 100 = 0 THEN ' Check every 100 samples to save CPU
DO WHILE _SNDRAWLEN > 0.2
_LIMIT 100 ' Give the CPU a rest while the sound card works
LOOP
END IF
NEXT i&
END SUB
@Petr 90% there i reckon...needs a better brain!
Unseeen



![[Image: 18te-Zeile-Fehler.jpg]](https://i.ibb.co/sv0rW3Xb/18te-Zeile-Fehler.jpg)
![[Image: Audio-funktioniert2025-12-25-170058.jpg]](https://i.ibb.co/fYdkD2D3/Audio-funktioniert2025-12-25-170058.jpg)
![[Image: Audio-Mikro-angeschlossen2025-12-25.jpg]](https://i.ibb.co/gZgmdsXh/Audio-Mikro-angeschlossen2025-12-25.jpg)