···
RadioStation* currentStation;
// VU meter levels (0.0 to 1.0)
···
DrawVolumeKnob(hdc, 350, 200, 30, g_radio.volume);
450
-
DrawSignalMeter(hdc, 450, 150, g_radio.signalStrength);
450
+
DrawSignalMeter(hdc, 450, 170, g_radio.signalStrength);
453
-
DrawVUMeter(hdc, 450, 180, g_audio.vuLevelLeft, g_audio.vuLevelRight);
453
+
DrawVUMeter(hdc, 450, 200, g_audio.vuLevelLeft, g_audio.vuLevelRight);
DrawPowerButton(hdc, 500, 120, 25, g_radio.power);
···
DeleteObject(stationFont);
489
-
SetBkMode(hdc, TRANSPARENT);
490
-
SetTextColor(hdc, RGB(255, 255, 255));
491
-
HFONT font = CreateFont(14, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
492
-
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
493
-
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
494
-
DEFAULT_PITCH | FF_SWISS, "Arial");
495
-
SelectObject(hdc, font);
497
-
TextOut(hdc, 180, 300, "TUNING", 6);
498
-
TextOut(hdc, 330, 260, "VOLUME", 6);
499
-
TextOut(hdc, 430, 200, "SIGNAL", 6);
500
-
TextOut(hdc, 485, 160, "POWER", 5);
502
-
DeleteObject(font);
void DrawFrequencyDisplay(HDC hdc, int x, int y, float frequency) {
···
DeleteObject(pointerPen);
617
+
// Draw label below the dial
618
+
SetBkMode(hdc, TRANSPARENT);
619
+
SetTextColor(hdc, RGB(255, 255, 255));
620
+
HFONT labelFont = CreateFont(14, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
621
+
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
622
+
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
623
+
DEFAULT_PITCH | FF_SWISS, "Arial");
624
+
SelectObject(hdc, labelFont);
625
+
SetTextAlign(hdc, TA_CENTER);
626
+
TextOut(hdc, x, y + radius + 15, "TUNING", 6);
627
+
DeleteObject(labelFont);
void DrawVolumeKnob(HDC hdc, int x, int y, int radius, float volume) {
···
MoveToEx(hdc, x, y, NULL);
LineTo(hdc, indicatorX, indicatorY);
DeleteObject(indicatorPen);
654
+
// Draw label below the knob
655
+
SetBkMode(hdc, TRANSPARENT);
656
+
SetTextColor(hdc, RGB(255, 255, 255));
657
+
HFONT labelFont = CreateFont(14, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
658
+
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
659
+
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
660
+
DEFAULT_PITCH | FF_SWISS, "Arial");
661
+
SelectObject(hdc, labelFont);
662
+
SetTextAlign(hdc, TA_CENTER);
663
+
TextOut(hdc, x, y + radius + 15, "VOLUME", 6);
664
+
DeleteObject(labelFont);
void DrawSignalMeter(HDC hdc, int x, int y, int strength) {
···
FillRect(hdc, &bar, barBrush);
697
+
// Draw label above the meter
698
+
SetBkMode(hdc, TRANSPARENT);
699
+
SetTextColor(hdc, RGB(255, 255, 255));
700
+
HFONT labelFont = CreateFont(14, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
701
+
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
702
+
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
703
+
DEFAULT_PITCH | FF_SWISS, "Arial");
704
+
SelectObject(hdc, labelFont);
705
+
SetTextAlign(hdc, TA_LEFT);
706
+
TextOut(hdc, x, y - 18, "SIGNAL", 6);
707
+
DeleteObject(labelFont);
void DrawVUMeter(HDC hdc, int x, int y, float leftLevel, float rightLevel) {
···
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS, "Arial");
SelectObject(hdc, smallFont);
710
-
TextOut(hdc, x + 2, y + 2, "VU", 2);
731
+
TextOut(hdc, x + 9, y + 2, "VU", 2);
// Draw left channel meter
int leftWidth = (int)(leftLevel * 70);
RECT leftBar = {x + 5, y + 12, x + 5 + leftWidth, y + 18};
716
-
COLORREF leftColor = leftLevel > 0.8f ? RGB(255, 0, 0) :
737
+
COLORREF leftColor = leftLevel > 0.8f ? RGB(255, 0, 0) :
leftLevel > 0.6f ? RGB(255, 255, 0) : RGB(0, 255, 0);
HBRUSH leftBrush = CreateSolidBrush(leftColor);
FillRect(hdc, &leftBar, leftBrush);
···
int rightWidth = (int)(rightLevel * 70);
RECT rightBar = {x + 5, y + 22, x + 5 + rightWidth, y + 28};
727
-
COLORREF rightColor = rightLevel > 0.8f ? RGB(255, 0, 0) :
748
+
COLORREF rightColor = rightLevel > 0.8f ? RGB(255, 0, 0) :
rightLevel > 0.6f ? RGB(255, 255, 0) : RGB(0, 255, 0);
HBRUSH rightBrush = CreateSolidBrush(rightColor);
FillRect(hdc, &rightBar, rightBrush);
DeleteObject(rightBrush);
734
-
// Draw channel labels
735
-
TextOut(hdc, x + 77, y + 10, "L", 1);
736
-
TextOut(hdc, x + 77, y + 20, "R", 1);
755
+
// Draw channel labels (better positioned)
756
+
TextOut(hdc, x + 77, y + 12, "L", 1);
757
+
TextOut(hdc, x + 77, y + 22, "R", 1);
HPEN scalePen = CreatePen(PS_SOLID, 1, RGB(80, 80, 80));
···
798
+
// Draw label above the button
799
+
SetBkMode(hdc, TRANSPARENT);
800
+
SetTextColor(hdc, RGB(255, 255, 255));
801
+
HFONT labelFont = CreateFont(14, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
802
+
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
803
+
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
804
+
DEFAULT_PITCH | FF_SWISS, "Arial");
805
+
SelectObject(hdc, labelFont);
806
+
SetTextAlign(hdc, TA_CENTER);
807
+
TextOut(hdc, x, y - radius - 18, "POWER", 5);
808
+
DeleteObject(labelFont);
int IsPointInCircle(int px, int py, int cx, int cy, int radius) {
···
DWORD CALLBACK StaticStreamProc(HSTREAM handle, void* buffer, DWORD length, void* user) {
short* samples = (short*)buffer;
DWORD sampleCount = length / sizeof(short);
// Get current time for oscillation
static DWORD startTime = GetTickCount();
DWORD currentTime = GetTickCount();
float timeSeconds = (currentTime - startTime) / 1000.0f;
// Create subtle volume oscillations (5-7% variation)
// Use multiple sine waves at different frequencies for natural variation
float oscillation1 = sin(timeSeconds * 0.7f) * 0.03f; // 3% slow oscillation
1037
-
float oscillation2 = sin(timeSeconds * 2.3f) * 0.02f; // 2% medium oscillation
1070
+
float oscillation2 = sin(timeSeconds * 2.3f) * 0.02f; // 2% medium oscillation
float oscillation3 = sin(timeSeconds * 5.1f) * 0.015f; // 1.5% fast oscillation
float volumeVariation = 1.0f + oscillation1 + oscillation2 + oscillation3;
// Generate white noise with volume variation
for (DWORD i = 0; i < sampleCount; i++) {
// Generate random value between -32767 and 32767
short baseNoise = (short)((rand() % 65535) - 32767);
// Apply volume variation
samples[i] = (short)(baseNoise * volumeVariation);
···
// Initialize levels to zero
g_audio.vuLevelLeft = 0.0f;
g_audio.vuLevelRight = 0.0f;
// Get levels from current stream if playing
if (g_audio.currentStream && BASS_ChannelIsActive(g_audio.currentStream) == BASS_ACTIVE_PLAYING) {
DWORD level = BASS_ChannelGetLevel(g_audio.currentStream);
···
g_audio.vuLevelRight = (float)HIWORD(level) / 32768.0f;
// Add static contribution if static is playing
if (g_audio.staticStream && BASS_ChannelIsActive(g_audio.staticStream) == BASS_ACTIVE_PLAYING) {
DWORD staticLevel = BASS_ChannelGetLevel(g_audio.staticStream);
float staticLeft = (float)LOWORD(staticLevel) / 32768.0f;
float staticRight = (float)HIWORD(staticLevel) / 32768.0f;
// Combine with existing levels (simulate mixing)
g_audio.vuLevelLeft = fmin(1.0f, g_audio.vuLevelLeft + staticLeft * 0.3f);
g_audio.vuLevelRight = fmin(1.0f, g_audio.vuLevelRight + staticRight * 0.3f);
// Apply some smoothing/decay for more realistic VU behavior
static float lastLeft = 0.0f, lastRight = 0.0f;
g_audio.vuLevelLeft = g_audio.vuLevelLeft * 0.7f + lastLeft * 0.3f;