KindElephant480
Asistan
- Katılım
- 14 Eylül 2017
- Mesajlar
- 363
- Reaksiyon puanı
- 44
- Puanları
- 28
1 yıldan fazla bir süredir NeoBleeper isimli SomethingUnreal kullanıcı adına sahip eski bir YouTuber'ın VB6 kullanarak geliştirdiği ve bilgisayarların anakartlarında bulunan sistem hoparlörü (normalde bilgisayarların sadece bip sesi çıkarması için kullanılan bir çeşit hoparlör) ile melodi çalmayı sağlayan Bleeper Music Maker programının C# dili ile yeniden yazdığım ve yapay zekâ destekli resimdeki yeniden yapımı olan bir program geliştiriyorum ancak listedeki notaları çalma özelliğini çalışır duruma getirdiğimden bu yana aşırı yavaş çalınma gibi çeşitli sorunlar yaşadım, bir süre sonra pencereyi gizleyene kadar aşırı yavaş çalınma sorunlarını çözdüm ancak videodaki gibi notaların uzunluklarının senkronize oynatmada senkronizasyonu bozacak şekilde hatalı hesaplandığını fark ettim ve sorunu System.Threading.Timers.Timer kullanan ve arayüz dondurmayan bekleme metodumdaki Timer'ı Stopwatch ile değiştirerek büyük oranda çözdüm.
Ancak videolardaki gibi iki programı karşılaştırdığımda orijinal Bleeper Music Maker programında notalar daha hızlı çalınırken NeoBleeper programımda orijinal Bleeper Music Maker programına göre daha yavaş çalındığını fark ettim ve bu kodlardaki yöntemler üzerinde sonuçları kesme veya yuvarlama işlemleri ve vuruş uzunluğu hesaplamaları konusunda denemeler yaptım ancak hiçbir sonuca ulaşamıyorum.
C#:
private async void play_music(int startIndex)
{
bool nonStopping = false;
EnableDisableCommonControls(false);
while (listViewNotes.SelectedItems.Count > 0 && is_music_playing)
{
nonStopping = trackBar_note_silence_ratio.Value == 100;
// Calculating note length and line length based on BPM
decimal millisecondsPerWholeNote = 0m;
if (Variables.bpm > 0)
{
// 60,000 ms / BPM = whole note duration in milliseconds / 240,000 ms = whole note duration in milliseconds for 4/4 time signature
millisecondsPerWholeNote = 240000m / Variables.bpm;
}
// Note length and line length calculators
int noteLength = note_length_calculator((double)millisecondsPerWholeNote);
int lineLength = line_length_calculator((double)millisecondsPerWholeNote);
// Note duration and wait duration calculations should be at least 1 ms
int calculatedNoteDuration = Math.Max(1, noteLength);
// Line length should also be at least 1 ms
int calculatedWaitDuration = Math.Max(calculatedNoteDuration, lineLength);
// Silence duration calculation
int silenceDuration = calculatedWaitDuration - calculatedNoteDuration;
// Play with MIDI output if enabled
if (Program.MIDIDevices.useMIDIoutput)
{
play_note_in_line_from_MIDIOutput(
listViewNotes.SelectedIndices[0],
checkBox_play_note1_played.Checked,
checkBox_play_note2_played.Checked,
checkBox_play_note3_played.Checked,
checkBox_play_note4_played.Checked,
calculatedNoteDuration
);
}
// Regular note playing logic
play_note_in_line(
checkBox_play_note1_played.Checked,
checkBox_play_note2_played.Checked,
checkBox_play_note3_played.Checked,
checkBox_play_note4_played.Checked,
calculatedNoteDuration,
nonStopping
);
// Apply the note length to the selected line in the ListView
if (silenceDuration > 0 && !nonStopping)
{
UpdateLabelVisible(false); // Hide the label
NonBlockingSleep.Sleep(silenceDuration);
}
// Select the next line in the ListView
await UpdateListViewSelectionSync(startIndex);
}
// Clean up after playing
if (nonStopping)
{
stopAllNotesAfterPlaying();
}
EnableDisableCommonControls(true);
}
private int note_length_calculator(double msPerWholeNote)
{
if (listViewNotes.SelectedItems == null || listViewNotes.SelectedItems.Count == 0 ||
listViewNotes.Items == null || listViewNotes.Items.Count == 0)
{
return 0;
}
int selectedLine = listViewNotes.SelectedIndices[0];
string noteType = listViewNotes.Items[selectedLine].SubItems[0].Text;
string modifier = listViewNotes.Items[selectedLine].SubItems[5].Text;
string articulation = listViewNotes.Items[selectedLine].SubItems[6].Text;
// Calculate the basic note length based on the note type
decimal noteFraction = noteType switch
{
"Whole" => 1m, // Whole note
"Half" => 0.5m, // Half note
"Quarter" => 0.25m, // Quarter note
"1/8" => 0.125m, // 1/8 note
"1/16" => 0.0625m, // 1/16 note
"1/32" => 0.03125m, // 1/32 note
_ => 0.25m, // Default: Quarter note
};
// Modifier factor (Dot, Triplet)
decimal modifierFactor = 1m;
if (!string.IsNullOrEmpty(modifier))
{
if (modifier.ToLowerInvariant().Contains("dot"))
modifierFactor = 1.5m; // Dotted note: 1.5x length
else if (modifier.ToLowerInvariant().Contains("tri"))
modifierFactor = 1m / 3m; // Triplet: 1/3x length
}
// Articulation factor - only affects fermata
decimal articulationFactor = 1m;
if (!string.IsNullOrEmpty(articulation))
{
if (articulation.ToLowerInvariant().Contains("sta"))
articulationFactor = 0.5m; // Staccato: 0.5x length
else if (articulation.ToLowerInvariant().Contains("spi"))
articulationFactor = 0.25m; // Spiccato: 0.25x length
else if (articulation.ToLowerInvariant().Contains("fer"))
articulationFactor = 2m; // Fermata: 2x length
}
// Note-silence ratio (from trackBar)
decimal silenceRatio = (decimal)trackBar_note_silence_ratio.Value / 100m;
// Calculate the total note length
decimal result = (decimal)msPerWholeNote * noteFraction * modifierFactor * articulationFactor * silenceRatio;
// Should be at least 1 ms
return Math.Max(1, (int)Math.Round(result, MidpointRounding.AwayFromZero));
}
private int line_length_calculator(double msPerWholeNote)
{
if (listViewNotes.SelectedItems == null || listViewNotes.SelectedItems.Count == 0 ||
listViewNotes.Items == null || listViewNotes.Items.Count == 0)
{
return 0;
}
int selectedLine = listViewNotes.SelectedIndices[0];
string noteType = listViewNotes.Items[selectedLine].SubItems[0].Text;
string modifier = listViewNotes.Items[selectedLine].SubItems[5].Text;
string articulation = listViewNotes.Items[selectedLine].SubItems[6].Text;
// Calculate the basic note length based on the note type
decimal noteFraction = noteType switch
{
"Whole" => 1m, // Whole note
"Half" => 0.5m, // Half note
"Quarter" => 0.25m, // Quarter note
"1/8" => 0.125m, // 1/8 note
"1/16" => 0.0625m, // 1/16 note
"1/32" => 0.03125m, // 1/32 note
_ => 0.25m, // Default: Quarter note
};
// Modifier factor (Dot, Triplet)
decimal modifierFactor = 1m;
if (!string.IsNullOrEmpty(modifier))
{
if (modifier.ToLowerInvariant().Contains("dot"))
modifierFactor = 1.5m; // Dotted: 1.5x length
else if (modifier.ToLowerInvariant().Contains("tri"))
modifierFactor = 1m / 3m; // Triplet: 1/3x length
}
// Articulation factor - only affects fermata
decimal articulationFactor = 1m;
if (!string.IsNullOrEmpty(articulation) && articulation.ToLowerInvariant().Contains("fer"))
{
articulationFactor = 2m; // Fermata: 2x length
}
// Staccato and Spiccato do not affect line length
// Calculate the total line length (without note-silence ratio)
decimal result = (decimal)msPerWholeNote * noteFraction * modifierFactor * articulationFactor;
// Should be at least 1 ms
return Math.Max(1, (int)Math.Round(result, MidpointRounding.AwayFromZero));
}
Sizce bu durumda programımın kodundaki hesaplama hataları hangi kısımlarda neden kaynaklanıyor olabilir?
Merak edenler için programımın GitHub sayfasının bağlantısı: NeoBleeper GitHub sayfası
Son düzenleme: