mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-26 23:36:32 +00:00
oscilloscope
This commit is contained in:
parent
53ed2bbc2e
commit
c92f7db428
5 changed files with 112 additions and 22 deletions
|
@ -21,12 +21,15 @@ U16 currentRate = InU16(ac97.nam + EXT_FRONT_RATE);
|
||||||
"currentRate: %d\n", currentRate;
|
"currentRate: %d\n", currentRate;
|
||||||
|
|
||||||
#include "Classes"
|
#include "Classes"
|
||||||
|
#include "Utils"
|
||||||
// include_noreindex "MIDIHandling"
|
// include_noreindex "MIDIHandling"
|
||||||
// include_noreindex "WaveformGen"
|
// include_noreindex "WaveformGen"
|
||||||
// include_noreindex "UITracker"
|
// include_noreindex "UITracker"
|
||||||
|
#include "Oscilloscope"
|
||||||
#include "MusicTracker"
|
#include "MusicTracker"
|
||||||
|
|
||||||
|
|
||||||
AutoComplete(0);
|
AutoComplete(0);
|
||||||
|
|
||||||
MusicTracker;
|
MusicTracker;
|
||||||
|
StartOscilloscope;
|
|
@ -42,7 +42,7 @@ U0 AudioPlayNote(U8 note, U8 velocity, U8 instrument) {
|
||||||
break;
|
break;
|
||||||
case SAMPLE:
|
case SAMPLE:
|
||||||
PlaySample(buffer, bufferSize, note, velocity);
|
PlaySample(buffer, bufferSize, note, velocity);
|
||||||
Print("Buffer first values: %d, %d, %d, %d...\n", buffer[0], buffer[1], buffer[2], buffer[3]);
|
//Print("Buffer first values: %d, %d, %d, %d...\n", buffer[0], buffer[1], buffer[2], buffer[3]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GenerateSineWave(buffer, bufferSize, freq, velocity);
|
GenerateSineWave(buffer, bufferSize, freq, velocity);
|
||||||
|
@ -51,35 +51,49 @@ U0 AudioPlayNote(U8 note, U8 velocity, U8 instrument) {
|
||||||
|
|
||||||
//ApplyEnvelope(buffer, SAMPLE_RATE); // TODO: Apply fade in and fade out
|
//ApplyEnvelope(buffer, SAMPLE_RATE); // TODO: Apply fade in and fade out
|
||||||
|
|
||||||
|
// I64 i;
|
||||||
|
// for (i = 0; i < bufferSize; i++) {
|
||||||
|
// // Copy data to the shared oscilloscope buffer
|
||||||
|
// gSharedBuffer[i] = buffer[i];
|
||||||
|
// }
|
||||||
|
|
||||||
// Play the buffer using the AC97 driver:
|
// Play the buffer using the AC97 driver:
|
||||||
AudioSFXPlay(buffer, bufferSize);
|
AudioSFXPlay(buffer, bufferSize);
|
||||||
// silly debug print
|
// silly debug print
|
||||||
if (instrument == SAMPLE)
|
|
||||||
"Instrument: $$RED$$ SAMPLE $$DKGRAY$$|$$FG$$ Note: $$YELLOW$$%d$$FG$$\n", note;
|
|
||||||
if (instrument == PULSE1)
|
if (instrument == PULSE1)
|
||||||
"Instrument: $$GREEN$$ PULSE1 $$DKGRAY$$|$$FG$$ Note: $$YELLOW$$%d$$FG$$\n", note;
|
"³ $$GREEN$$PULSE1 $$FG$$³ $$YELLOW$$%d$$FG$$\t³", note;
|
||||||
if (instrument == PULSE2)
|
if (instrument == PULSE2)
|
||||||
"Instrument: $$CYAN$$ PULSE2 $$DKGRAY$$|$$FG$$ Note: $$YELLOW$$%d$$FG$$\n", note;
|
"³ $$CYAN$$PULSE2 $$FG$$³ $$YELLOW$$%d$$FG$$\t³", note;
|
||||||
if (instrument == TRIANGLE)
|
if (instrument == TRIANGLE)
|
||||||
"Instrument: $$YELLOW$$ TRIANGLE $$DKGRAY$$|$$FG$$ Note: $$YELLOW$$%d$$FG$$\n", note;
|
"³ $$YELLOW$$TRIANGLE $$FG$$³ $$YELLOW$$%d$$FG$$\t³", note;
|
||||||
if (instrument == NOISE)
|
if (instrument == NOISE)
|
||||||
"Instrument: $$BROWN$$ NOISE $$DKGRAY$$|$$FG$$ Note: $$YELLOW$$%d$$FG$$\n", note;
|
"³ $$BROWN$$NOISE $$FG$$³ $$YELLOW$$%d$$FG$$\t³", note;
|
||||||
|
if (instrument == SAMPLE)
|
||||||
|
"³ $$RED$$SAMPLE $$FG$$³ $$YELLOW$$%d$$FG$$\t³", note;
|
||||||
|
if (instrument == INSTRUMENT_NONE)
|
||||||
|
"³ ³ \t³", note;
|
||||||
|
|
||||||
|
"\n";
|
||||||
Free(buffer);
|
Free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
U0 PlayPattern(Pattern *pattern) {
|
U0 PlayPattern(Pattern *pattern) {
|
||||||
I64 row;
|
I64 row;
|
||||||
NoteCell *cell;
|
NoteCell *cell;
|
||||||
|
"ÚÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄ¿\n";
|
||||||
|
"³ INSTRUMENT ³ NOTE ³\n";
|
||||||
|
"ÃÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄ´\n";
|
||||||
for (row = 0; row < TRACK_LENGTH; row++) {
|
for (row = 0; row < TRACK_LENGTH; row++) {
|
||||||
cell = &pattern->cells[row];
|
cell = &pattern->cells[row];
|
||||||
if (cell->note) {
|
if (cell->note) {
|
||||||
AudioPlayNote(cell->note, cell->velocity, cell->instrument);
|
AudioPlayNote(cell->note, cell->velocity, cell->instrument);
|
||||||
|
if (row < TRACK_LENGTH-1) "ÃÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄ´\n";
|
||||||
}
|
}
|
||||||
if (cell->instrument == SAMPLE) Sleep(1000); // wait for 6sec for the 7sec sample test
|
if (cell->instrument == SAMPLE) Sleep(1000); // wait for 6sec for the 7sec sample test
|
||||||
//Sleep(1200); // Adjust for tempo
|
//Sleep(1200); // Adjust for tempo
|
||||||
Sleep(300);
|
Sleep(300);
|
||||||
}
|
}
|
||||||
|
"ÀÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÙ\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
U0 EnterPattern(Pattern *pattern) {
|
U0 EnterPattern(Pattern *pattern) {
|
||||||
|
@ -87,7 +101,7 @@ U0 EnterPattern(Pattern *pattern) {
|
||||||
NoteCell *cell;
|
NoteCell *cell;
|
||||||
for (row = 0; row < TRACK_LENGTH; row++) {
|
for (row = 0; row < TRACK_LENGTH; row++) {
|
||||||
cell = &pattern->cells[row];
|
cell = &pattern->cells[row];
|
||||||
Print("Enter note for row %d (0-127, 0 for none): ", row);
|
Print("Enter note for row $$LTGREEN$$%d$$FG$$ (0-127, 0 for none): ", row);
|
||||||
cell->note = KeyGet(&sc);
|
cell->note = KeyGet(&sc);
|
||||||
"%d\n", cell->note;
|
"%d\n", cell->note;
|
||||||
if (cell->note) {
|
if (cell->note) {
|
||||||
|
@ -118,11 +132,10 @@ U0 EnterPattern(Pattern *pattern) {
|
||||||
"SAMPLE\n";
|
"SAMPLE\n";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Print("Invalid choice.\n");
|
|
||||||
cell->instrument = INSTRUMENT_NONE;
|
cell->instrument = INSTRUMENT_NONE;
|
||||||
"SINE\n";
|
"SINE\n";
|
||||||
break;
|
break;
|
||||||
// return;
|
// return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioPlayNote(cell->note, cell->velocity, cell->instrument);
|
AudioPlayNote(cell->note, cell->velocity, cell->instrument);
|
||||||
|
@ -216,4 +229,5 @@ U0 MusicTracker() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CleanupWaveformGen(); // Free the sample buffer
|
CleanupWaveformGen(); // Free the sample buffer
|
||||||
|
Kill("Oscilloscope");
|
||||||
}
|
}
|
||||||
|
|
73
src/Home/Tracker/Oscilloscope.ZC
Executable file
73
src/Home/Tracker/Oscilloscope.ZC
Executable file
|
@ -0,0 +1,73 @@
|
||||||
|
// Globals
|
||||||
|
U32 *gSharedBuffer;
|
||||||
|
I64 gSharedBufferPosition = 0;
|
||||||
|
I64 gSharedBufferSize;
|
||||||
|
|
||||||
|
// Initialize shared buffer
|
||||||
|
U0 InitSharedBuffer(I64 size) {
|
||||||
|
gSharedBuffer = MAlloc(size * sizeof(U32));
|
||||||
|
gSharedBufferSize = size;
|
||||||
|
gSharedBufferPosition = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update shared buffer in your audio playback function
|
||||||
|
U0 UpdateSharedBuffer(U32 *buffer, I64 size) {
|
||||||
|
I64 i;
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
gSharedBuffer[gSharedBufferPosition] = buffer[i];
|
||||||
|
gSharedBufferPosition = (gSharedBufferPosition + 1) % gSharedBufferSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
U0 OscilloscopeDraw() {
|
||||||
|
I64 i, y;
|
||||||
|
//GrClear(0); // Clear the screen
|
||||||
|
|
||||||
|
I64 startPosition = gSharedBufferPosition;
|
||||||
|
for (i = 0; i < 400; i++) {
|
||||||
|
I16 sample_value = (gSharedBuffer[startPosition] & 0xFFFF) - 32768; // extract left channel and center around 0
|
||||||
|
F64 normalized_sample = ToF64(sample_value) / 32768.0;
|
||||||
|
y = 300 / 2 - (normalized_sample * 300 / 2);
|
||||||
|
|
||||||
|
GrPlot(i, y, WHITE); // Using GrPlot instead of DrawPoint
|
||||||
|
|
||||||
|
startPosition = (startPosition + 1) % gSharedBufferSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Oscilloscope task
|
||||||
|
U0 OscilloscopeTask() {
|
||||||
|
// Fs->draw_it = &OscilloscopeDraw; // Set the draw callback
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
Refresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 StartOscilloscope() {
|
||||||
|
InitSharedBuffer(44100); // For example, buffer to store 1 second of audio at 44100Hz
|
||||||
|
|
||||||
|
// SettingsPush(); // Push current settings
|
||||||
|
// Fs->win_width = 400; // Width of the oscilloscope window
|
||||||
|
// Fs->win_height = 300; // Height of the oscilloscope window
|
||||||
|
WinHorz((TEXT_COLS / 2) - 200,
|
||||||
|
(TEXT_COLS / 2) - 200 + (200 - 1),
|
||||||
|
Fs);
|
||||||
|
WinVert((TEXT_ROWS / 2) - 150,
|
||||||
|
(TEXT_ROWS / 2) - 150 + (Fs->win_height - 1),
|
||||||
|
Fs);
|
||||||
|
// Fs->border_src = BDS_CONST;
|
||||||
|
// Fs->border_attr = LTGREEN << 4 + WHITE;
|
||||||
|
// StrCopy(Fs->task_title, "Oscilloscope");
|
||||||
|
|
||||||
|
Fs->draw_it = &OscilloscopeDraw; // Set the draw callback
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
Refresh;
|
||||||
|
}
|
||||||
|
// Spawn("Oscilloscope", OscilloscopeTask); // Start the oscilloscope task
|
||||||
|
|
||||||
|
// SettingsPop(); // Pop settings
|
||||||
|
}
|
9
src/Home/Tracker/Utils.ZC
Executable file
9
src/Home/Tracker/Utils.ZC
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
F64 RoundToNearestHalf(F64 value) {
|
||||||
|
return Round(value * 2.0) / 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
F64 GetPlaybackRateMultiplier(U8 targetNote, U8 referenceNote) {
|
||||||
|
I64 semitoneDifference = targetNote - referenceNote;
|
||||||
|
return Pow(2.0, semitoneDifference / 12.0);
|
||||||
|
}
|
||||||
|
|
|
@ -223,15 +223,6 @@ U0 LoadSample(U8 *filename) {
|
||||||
// return ClampToI16(RoundF64(result));
|
// return ClampToI16(RoundF64(result));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
F64 RoundToNearestHalf(F64 value) {
|
|
||||||
return Round(value * 2.0) / 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
F64 GetPlaybackRateMultiplier(U8 targetNote, U8 referenceNote) {
|
|
||||||
I64 semitoneDifference = targetNote - referenceNote;
|
|
||||||
return Pow(2.0, semitoneDifference / 12.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
U0 PlaySample(U32 *buffer, I64 duration, U8 note, U8 velocity) {
|
U0 PlaySample(U32 *buffer, I64 duration, U8 note, U8 velocity) {
|
||||||
if (!gSampleData || !gSampleSize) {
|
if (!gSampleData || !gSampleSize) {
|
||||||
Print("Sample not loaded.\n");
|
Print("Sample not loaded.\n");
|
||||||
|
|
Loading…
Reference in a new issue