EKSPLORASI MUSIK MODERN MIKROTONAL MENGGUNAKAN SKALA 12 TET (20 NADA PER OKTAF)
Bagaimana caranya jika nada nada sistem 12 TET (20 nada per oktaf) tetsebut dibunyiksn oleh alat/instrumen piano
Jika nada-nada sistem 12-TET (Twelve-tone Equal Temperament) dengan 20 nada per oktaf dibunyikan oleh alat/instrumen seperti piano, beberapa langkah perlu dilakukan untuk menghasilkan suara yang realistis, baik secara fisik (menggunakan piano fisik) maupun secara digital (dengan simulasi).
1. Memahami Sistem 12-TET dengan 20 Nada per Oktaf
Dalam 12-TET tradisional, satu oktaf dibagi menjadi 12 nada dengan interval semitone yang sama. Dalam 20 nada per oktaf, oktaf dibagi menjadi 20 interval yang sama besar. Artinya, setiap interval memiliki frekuensi yang ditentukan oleh rumus:
f_n = f_0 × {3 pangkat (1/20) pangkat n}
Kode:
f_{n} = f_{0} \cdot (3^{(1/20)})^{n}
Di mana:
- f_0 : Frekuensi dasar (misalnya 440 Hz untuk A4).
- n : Jarak nada dari nada dasar.
2. Membunyikan Nada di Piano Fisik
Untuk piano fisik:
- Sebuah piano standar 88 tuts tidak dirancang untuk menghasilkan nada di luar sistem 12-TET.
- Diperlukan penyetelan ulang piano fisik untuk menyesuaikan nada dalam sistem 20-TET, yang melibatkan penyesuaian ketegangan senar. Namun, ini jarang dilakukan karena akan merusak standar piano.
- Sebagai alternatif, Anda dapat menggunakan instrumen yang dirancang khusus, seperti keyboard mikrotonal atau piano yang dapat disesuaikan (misalnya, Seaboard RISE atau H-Piano).
3. Membunyikan Nada secara Digital dengan Piano Virtual
Jika ingin membunyikan nada dalam 20-TET secara digital, kita dapat menggunakan piano virtual atau simulasi instrumen MIDI. Berikut langkah-langkahnya:
a. Menghitung Frekuensi 20 Nada per Oktaf
Berikut adalah kode Python untuk menghitung frekuensi:
import numpy as np
# Frekuensi dasar (A4)
base_frequency = 440.0 # Hz
notes_per_octave = 20
# Menghitung frekuensi untuk 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=1):
frequencies = []
for octave in range(octaves):
for n in range(notes_per_octave):
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3))
base_freq *= 3 # Naik satu oktaf
return frequencies
# Hitung frekuensi (3 oktaf sebagai contoh)
frequencies = calculate_20_tet_frequencies(base_frequency, notes_per_octave, octaves=3)
print("Frequencies (20-TET):", frequencies)
Output ini memberikan daftar frekuensi 20 nada per oktaf sebanyak 3 oktaf.
---
b. Membunyikan Nada Digital dengan Pygame
Menggunakan kode sebelumnya untuk membunyikan nada, sesuaikan frekuensi untuk 20-TET:
import numpy as np
import pygame
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Fungsi untuk memainkan nada
def play_tone(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
sound = pygame.sndarray.make_sound(wave)
sound.play(-1)
pygame.time.delay(int(duration * 1000))
sound.stop()
# Frekuensi 20-TET
frequencies = calculate_20_tet_frequencies(440.0, 20, octaves=1)
# Mainkan nada satu per satu
for freq in frequencies:
print(f"Playing {freq} Hz")
play_tone(freq, duration=0.5) # Setiap nada dimainkan selama 0.5 detik
---
c. Menggunakan Piano Virtual atau DAW
Jika menggunakan DAW (Digital Audio Workstation) atau perangkat lunak piano virtual:
1. Gunakan plugin seperti Kontakt, Pianoteq, atau Falcon yang mendukung sistem penyetelan mikrotonal.
2. Buat skala 20-TET dalam format Scala (.scl) dan impor ke instrumen virtual.
3. Buat MIDI atau peta tuts piano yang disesuaikan dengan skala 20-TET.
---
4. Hasil Akhir
Menggunakan langkah-langkah ini, Anda dapat:
- Menyetel ulang piano fisik untuk 20-TET (dengan risiko kerusakan).
- Membunyikan nada 20-TET secara digital menggunakan simulasi piano virtual.
- Menghasilkan file audio untuk setiap nada, seperti pada kode yang telah diberikan sebelumnya.
Selanjutnya tolong tambahkan oktafnya sebanyak 5 oktaf yaitu oktaf ke-2, ke-3, ke_4, ke_5, dan oktaf ke_6. Maksud saya bagaimana oktaf dari nada A4 turun sebanyak 2 oktaf ke bawah, dan naik 3 oktaf ke atas.
Berikut adalah kode Python yang telah dimodifikasi untuk menghitung frekuensi 20-TET dengan total 5 oktaf (oktaf ke-2 hingga ke-6):
Untuk menghitung frekuensi 20-TET yang turun sebanyak 2 oktaf dari base_frequency (misalnya A4, 440 Hz), kita dapat memodifikasi fungsi untuk menurunkan frekuensi dasar sebanyak 2 oktaf terlebih dahulu. Frekuensi turun oktaf dihitung dengan membagi frekuensi dasar dengan 3 untuk setiap oktaf yang diturunkan.
Berikut adalah kode yang telah dimodifikasi:
import numpy as np
# Frekuensi dasar (A4)
base_frequency = 440.00 # Hz
notes_per_octave = 20
# Menghitung frekuensi untuk 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=1, down_octaves=0):
frequencies = []
# Turunkan base_freq sebanyak down_octaves
base_freq /= 3 ** down_octaves
for octave in range(octaves + down_octaves):
for n in range(notes_per_octave):
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3))
base_freq *= 3 # Naik satu oktaf
return frequencies
# Hitung frekuensi untuk 3 oktaf ke atas dan 2 oktaf ke bawah
frequencies = calculate_20_tet_frequencies(base_frequency, notes_per_octave, octaves=3, down_octaves=2)
# Menampilkan hasil
print("Frequencies (20-TET including 2 octaves down):")
for i, freq in enumerate(frequencies, start=1):
print(f"Note {i}: {freq} Hz")
Penjelasan:
1. Base Frequency: Mulai dari 440 Hz (A4) sebagai frekuensi dasar.
2. Notes per Octave: Setiap oktaf memiliki 20 nada.
3. Octaves: Jumlah oktaf diperluas menjadi 5 oktaf.
4. Formula Frekuensi:
Setiap nada dihitung menggunakan formula:
f_n = f_base × {3 pangkat (n / notes per octave)}
Kode:
f(n) = f_{\text{base}} \times (3^{\frac{n}{\text{notes per octave}}})
Penjelasan lebih lanjut:
1. Penurunan 2 Oktaf:
- Frekuensi dasar diturunkan dengan membagi nilai base_frequency sebanyak {3 pangkat (doen_oktaves)}
- Untuk 2 oktaf ke bawah:
f' = f_base / (3 pangkat 2)
Kode:
f' = f_{\text{base}} / 3^2
Fungsi ini menghitung semua nada, termasuk yang ada di oktaf yang turun dan naik.
2. Parameter Baru:
down_octaves menentukan berapa banyak oktaf yang akan dihitung ke bawah sebelum menghitung ke atas.
Output:
Kode ini akan mencetak semua frekuensi untuk 100 nada (20 nada x 5 oktaf) dalam format daftar dan setiap nilai individu dengan unit Hz.
Kode akan menghasilkan daftar frekuensi yang dimulai dari 2 oktaf di bawah base_frequency hingga 3 oktaf di atas base_frequency, totalnya mencakup nada dari 5 oktaf.
Jika kode dieksekusi maka akan menghasilkan:
Frequencies (20-TET 3 octave up including 2 octaves down):
Note 1: 48.889 Hz
Note 2: 51.65 Hz
Note 3: 54.566 Hz
Note 4: 57.647 Hz
Note 5: 60.902 Hz
Note 6: 64.341 Hz
Note 7: 67.975 Hz
Note 8: 71.813 Hz
Note 9: 75.868 Hz
Note 10: 80.152 Hz
Note 11: 84.678 Hz
Note 12: 89.46 Hz
Note 13: 94.511 Hz
Note 14: 99.848 Hz
Note 15: 105.486 Hz
Note 16: 111.443 Hz
Note 17: 117.735 Hz
Note 18: 124.384 Hz
Note 19: 131.407 Hz
Note 20: 138.827 Hz
Note 21: 146.667 Hz
Note 22: 154.949 Hz
Note 23: 163.698 Hz
Note 24: 172.942 Hz
Note 25: 182.707 Hz
Note 26: 193.024 Hz
Note 27: 203.924 Hz
Note 28: 215.439 Hz
Note 29: 227.604 Hz
Note 30: 240.456 Hz
Note 31: 254.034 Hz
Note 32: 268.379 Hz
Note 33: 283.533 Hz
Note 34: 299.544 Hz
Note 35: 316.458 Hz
Note 36: 334.328 Hz
Note 37: 353.206 Hz
Note 38: 373.151 Hz
Note 39: 394.222 Hz
Note 40: 416.482 Hz
Note 41: 440.0 Hz
Note 42: 464.846 Hz
Note 43: 491.094 Hz
Note 44: 518.825 Hz
Note 45: 548.122 Hz
Note 46: 579.073 Hz
Note 47: 611.771 Hz
Note 48: 646.316 Hz
Note 49: 682.812 Hz
Note 50: 721.369 Hz
Note 51: 762.102 Hz
Note 52: 805.136 Hz
Note 53: 850.6 Hz
Note 54: 898.631 Hz
Note 55: 949.374 Hz
Note 56: 1002.983 Hz
Note 57: 1059.619 Hz
Note 58: 1119.453 Hz
Note 59: 1182.665 Hz
Note 60: 1249.447 Hz
Note 61: 1320.0 Hz
Note 62: 1394.537 Hz
Note 63: 1473.283 Hz
Note 64: 1556.475 Hz
Note 65: 1644.365 Hz
Note 66: 1737.218 Hz
Note 67: 1835.314 Hz
Note 68: 1938.949 Hz
Note 69: 2048.436 Hz
Note 70: 2164.106 Hz
Note 71: 2286.307 Hz
Note 72: 2415.409 Hz
Note 73: 2551.8 Hz
Note 74: 2695.894 Hz
Note 75: 2848.123 Hz
Note 76: 3008.949 Hz
Note 77: 3178.857 Hz
Note 78: 3358.358 Hz
Note 79: 3547.996 Hz
Note 80: 3748.341 Hz
Note 81: 3960.0 Hz
Note 82: 4183.611 Hz
Note 83: 4419.848 Hz
Note 84: 4669.425 Hz
Note 85: 4933.095 Hz
Note 86: 5211.653 Hz
Note 87: 5505.941 Hz
Note 88: 5816.847 Hz
Note 89: 6145.308 Hz
Note 90: 6492.318 Hz
Note 91: 6858.921 Hz
Note 92: 7246.226 Hz
Note 93: 7655.401 Hz
Note 94: 8087.681 Hz
Note 95: 8544.37 Hz
Note 96: 9026.848 Hz
Note 97: 9536.57 Hz
Note 98: 10075.074 Hz
Note 99: 10643.987 Hz
Note 100: 11245.024 Hz
[Program finished]
:Kemudian jika kode yang berikut ini dijalankan:
import numpy as np
import pygame
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Fungsi untuk memainkan nada
def play_tone(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
sound = pygame.sndarray.make_sound(wave)
sound.play(-1)
pygame.time.delay(int(duration * 1000))
sound.stop()
# Frekuensi 20-TET
frequencies = calculate_20_tet_frequencies(440.0, 20, octaves=2)
# Mainkan nada satu per satu
for freq in frequencies:
print(f"Playing {freq} Hz")
play_tone(freq, duration=0.8) # Setiap nada dimainkan selama 0.8 detik
Maka muncul error:
pygame 2.5.0 (SDL 2.28.0, Python 3.11.4)
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "/data/user/0/ru.iiec.pydroid3/files/temp_iiec_codefile.py", line 17, in <module>
frequencies = calculate_20_tet_frequencies(440.0, 20, octaves=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
NameError: name 'calculate_20_tet_frequencies' is not defined
Error NameError: name 'calculate_20_tet_frequencies' is not defined terjadi karena fungsi calculate_20_tet_frequencies belum didefinisikan atau diimpor dalam file kode yang sedang dijalankan.
Untuk mengatasi masalah ini, pastikan bahwa fungsi calculate_20_tet_frequencies sudah didefinisikan sebelum digunakan dalam kode utama. Berikut adalah kode lengkap yang menggabungkan fungsi calculate_20_tet_frequencies dengan kode untuk memainkan nada:
Kode Lengkap:
import numpy as np
import pygame
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Fungsi untuk menghitung frekuensi 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=2):
frequencies = []
for octave in range(octaves):
for n in range(notes_per_octave):
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3))
base_freq *= 3 # Naik satu oktaf
return frequencies
# Fungsi untuk memainkan nada
def play_tone(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
sound = pygame.sndarray.make_sound(wave)
sound.play(-1) # Loop satu kali
pygame.time.delay(int(duration * 1000)) # Durasi dalam milidetik
sound.stop()
# Hitung frekuensi untuk 2 oktaf
frequencies = calculate_20_tet_frequencies(440.0, 20, octaves=2)
# Mainkan nada satu per satu
for freq in frequencies:
print(f"Playing {freq} Hz")
play_tone(freq, duration=0.8) # Setiap nada dimainkan selama 0.8 detik
Penjelasan:
1. Integrasi Fungsi:
Fungsi calculate_20_tet_frequencies didefinisikan sebelum digunakan dalam variabel frequencies. Hal ini memastikan bahwa program mengenali fungsi tersebut.
2. Urutan Eksekusi:
Panggilan ke calculate_20_tet_frequencies terjadi setelah fungsi itu tersedia di dalam kode.
Nada yang dihasilkan dari frequencies kemudian digunakan dalam play_tone.
3. Lingkungan Runtime:
Pastikan semua dependensi seperti pygame sudah terinstal dengan benar di sistem Anda. Anda dapat menginstalnya dengan:
pip install pygame
Output:
Setelah dijalankan, kode ini akan menghitung frekuensi untuk 2 oktaf dalam sistem 20-TET dan memutar nada-nada tersebut satu per satu dengan durasi 0.8 detik per nada.
Berikut adalah penjelasan arti dari setiap bagian penulisan kode:
1. Mengimpor Modul
import numpy as np
import pygame
numpy (np): Digunakan untuk manipulasi array numerik dan operasi matematika (misalnya np.linspace untuk membuat array linier dan np.sin untuk membuat gelombang sinus).
pygame: Sebuah pustaka Python untuk pengembangan game, di sini digunakan untuk menginisialisasi mixer audio dan memainkan suara.
2. Inisialisasi Mixer Pygame
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
frequency=44100: Sample rate audio dalam Hertz (standar untuk audio digital).
size=-16: Format audio 16-bit signed (nilai negatif menunjukkan signed integer).
channels=1: Mono (satu saluran audio). Gunakan 2 untuk stereo.
buffer=512: Ukuran buffer audio, menentukan latensi antara sinyal yang dikirim ke speaker.
3. Fungsi untuk Menghitung Frekuensi Sistem 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=2):
frequencies = []
for octave in range(octaves): # Loop untuk setiap oktaf
for n in range(notes_per_octave): # Loop untuk setiap nada dalam oktaf
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3)) # Simpan frekuensi dengan 3 desimal
base_freq *= 3 # Kalikan frekuensi dasar dengan 3 untuk naik ke oktaf berikutnya
return frequencies
base_freq: Frekuensi dasar (contoh: A4 = 440 Hz).
notes_per_octave: Jumlah nada dalam satu oktaf (20 untuk sistem 20-TET).
octaves: Jumlah oktaf yang akan dihitung.
3 ** (n / notes_per_octave): Rumus untuk menaikkan frekuensi nada berdasarkan sistem 20-TET.
round(freq, 3): Membulatkan nilai frekuensi ke 3 desimal untuk presisi.
4. Fungsi untuk Memainkan Nada
def play_tone(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
sound = pygame.sndarray.make_sound(wave)
sound.play(-1) # Loop suara satu kali
pygame.time.delay(int(duration * 1000)) # Tunggu selama durasi nada
sound.stop()
frequency: Frekuensi nada yang akan dimainkan (dalam Hertz).
duration: Durasi nada dalam detik.
amplitude=0.5: Amplitudo suara (0.0 hingga 1.0, di mana 1.0 adalah volume maksimum).
sample_rate=44100: Jumlah sampel per detik untuk menghasilkan suara.
np.linspace(0, duration, int(sample_rate * duration), endpoint=False): Membuat array waktu t untuk durasi suara.
np.sin(2 * np.pi * frequency * t): Membuat gelombang sinus dengan frekuensi tertentu (menggunakan 2 * np.pi bukan 3 * np.pi untuk gelombang sinus standar).
* 32767: Mengonversi gelombang sinus ke format 16-bit signed integer.
pygame.sndarray.make_sound(wave): Mengubah array gelombang menjadi objek suara pygame.
sound.play(-1): Memutar suara.
pygame.time.delay(int(duration * 1000)): Memberikan waktu jeda sesuai durasi nada.
sound.stop(): Menghentikan suara setelah selesai dimainkan.
5. Menghitung Frekuensi dan Memutar Nada
frequencies = calculate_20_tet_frequencies(440.0, 20, octaves=2)
Menghitung frekuensi untuk 2 oktaf dalam sistem 20-TET dimulai dari frekuensi dasar 440 Hz.
for freq in frequencies:
print(f"Playing {freq} Hz")
play_tone(freq, duration=0.8) # Mainkan setiap nada selama 0.8 detik
Melakukan iterasi melalui daftar frequencies, mencetak nilai frekuensi, dan memutar nada menggunakan play_tone.
Catatan Kesalahan
3 * np.pi seharusnya 2 * np.pi dalam fungsi play_tone, karena 1 periode gelombang sinus adalah 2 phi.
Kode yang benar pada fungsi play_tone:
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
Output
Kode akan menghasilkan:
1. Daftar frekuensi dalam sistem 20-TET untuk 2 oktaf.
2. Setiap nada diputar selama 0.8 detik secara berurutan menggunakan Pygame.
3. Tampilan frekuensi nada di terminal, misalnya:
Playing 440.0 Hz
Playing 465.875 Hz
...
Playing 3520.0 Hz
Modifikasi kode berikut untuk menghasilkan output bunyi nada 2 oktaf, dan juga menghasilkan file berformat wav.
Kode:
import numpy as np
import pygame
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Fungsi untuk menghitung frekuensi 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=1):
frequencies = []
for octave in range(octaves):
for n in range(notes_per_octave):
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3))
base_freq *= 3 # Naik satu oktaf
return frequencies
# Fungsi untuk memainkan nada
def play_tone(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
sound = pygame.sndarray.make_sound(wave)
sound.play(-1) # Loop satu kali
pygame.time.delay(int(duration * 1000)) # Durasi dalam milidetik
sound.stop()
# Hitung frekuensi untuk 2 oktaf
frequencies = calculate_20_tet_frequencies(440.00, 20, octaves=2)
# Mainkan nada satu per satu
for freq in frequencies:
print(f"Playing {freq} Hz")
play_tone(freq, duration=0.8) # Setiap nada dimainkan selama 0.8 detik
Berikut adalah modifikasi kode untuk memainkan bunyi 2 oktaf dalam sistem 20-TET dan menyimpannya ke dalam file berformat WAV:
Kode Modifikasi
import numpy as np
import pygame
import wave
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Fungsi untuk menghitung frekuensi 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=1):
frequencies = []
for octave in range(octaves):
for n in range(notes_per_octave):
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3))
base_freq *= 3 # Naik satu oktaf
return frequencies
# Fungsi untuk membuat gelombang nada
def generate_wave(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
return wave
# Fungsi untuk menyimpan gelombang ke file WAV
def save_to_wav(filename, wave_data, sample_rate=44100):
with wave.open(filename, 'w') as wav_file:
wav_file.setnchannels(1) # Mono
wav_file.setsampwidth(2) # 16-bit
wav_file.setframerate(sample_rate)
wav_file.writeframes(wave_data.tobytes())
# Fungsi untuk memainkan nada
def play_tone(frequency, duration, amplitude=0.5, sample_rate=44100):
wave_data = generate_wave(frequency, duration, amplitude, sample_rate)
sound = pygame.sndarray.make_sound(wave_data)
sound.play(-1) # Loop satu kali
pygame.time.delay(int(duration * 1000)) # Durasi dalam milidetik
sound.stop()
return wave_data
# Hitung frekuensi untuk 2 oktaf
frequencies = calculate_20_tet_frequencies(440.00, 20, octaves=2)
# Buffer untuk menyimpan semua gelombang suara
all_waves = []
# Mainkan nada satu per satu dan tambahkan ke buffer WAV
for freq in frequencies:
print(f"Playing {freq} Hz")
wave_data = play_tone(freq, duration=0.8) # Mainkan nada
all_waves.append(wave_data)
# Gabungkan semua gelombang menjadi satu
final_wave = np.concatenate(all_waves)
# Simpan ke file WAV
save_to_wav("20_TET_2_Octaves.wav", final_wave)
print("File 20_TET_2_Octaves.wav berhasil dibuat!")
Penjelasan Modifikasi
1. generate_wave:
Fungsi ini membuat gelombang sinus untuk nada tertentu, digunakan untuk memutar suara dan menyimpan data suara.
2. save_to_wav:
Menyimpan data gelombang ke dalam file WAV:
Mono: Satu saluran.
16-bit signed: Format suara.
3. all_waves:
Menyimpan semua gelombang suara dari frekuensi yang dihitung.
Gelombang dari semua nada digabungkan dengan np.concatenate sebelum disimpan.
4. Output:
Memainkan setiap nada selama 0.8 detik.
Menyimpan semua nada ke dalam file bernama 20_TET_2_Octaves.wav.
Hasil
Audio: Setiap nada dari 2 oktaf sistem 20-TET dimainkan secara berurutan.
File WAV: File bernama 20_TET_2_Octaves.wav berisi semua nada yang telah dimainkan. File ini dapat diputar menggunakan pemutar audio.
Kode yang benar seharusnya adalah berikut ini, dimana A4 = 416.49 Hz (bukan A4=440.00 Hz. Nada yang berfrekwensi 440 Hz betada di urutan ke_2)
Kode yang benar:
import numpy as np
import pygame
import wave
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Fungsi untuk menghitung frekuensi 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=1):
frequencies = []
for octave in range(octaves):
for n in range(notes_per_octave):
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3))
base_freq *= 3 # Naik satu oktaf
return frequencies
# Fungsi untuk membuat gelombang nada
def generate_wave(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
return wave
# Fungsi untuk menyimpan gelombang ke file WAV
def save_to_wav(filename, wave_data, sample_rate=44100):
with wave.open(filename, 'w') as wav_file:
wav_file.setnchannels(1) # Mono
wav_file.setsampwidth(2) # 16-bit
wav_file.setframerate(sample_rate)
wav_file.writeframes(wave_data.tobytes())
# Fungsi untuk memainkan nada
def play_tone(frequency, duration, amplitude=0.5, sample_rate=44100):
wave_data = generate_wave(frequency, duration, amplitude, sample_rate)
sound = pygame.sndarray.make_sound(wave_data)
sound.play(-1) # Loop satu kali
pygame.time.delay(int(duration * 1000)) # Durasi dalam milidetik
sound.stop()
return wave_data
# Hitung frekuensi untuk 2 oktaf
frequencies = calculate_20_tet_frequencies(416.49, 20, octaves=2)
# Buffer untuk menyimpan semua gelombang suara
all_waves = []
# Mainkan nada satu per satu dan tambahkan ke buffer WAV
for freq in frequencies:
print(f"Playing {freq} Hz")
wave_data = play_tone(freq, duration=0.8) # Mainkan nada
all_waves.append(wave_data)
# Gabungkan semua gelombang menjadi satu
final_wave = np.concatenate(all_waves)
# Simpan ke file WAV
save_to_wav("20_TET_2_Octaves.wav", final_wave)
print("File 20_TET_2_Octaves.wav berhasil dibuat!")
Kode yang Anda berikan sudah benar untuk menghasilkan nada dengan frekuensi dasar A4 = 416.49 Hz sebagai nada awal (berbeda dari standar 440 Hz), dan menghasilkan file WAV yang menyimpan semua nada dalam sistem 20-TET untuk 2 oktaf.
Berikut adalah poin penting dari kode Anda:
Penyesuaian Utama:
1. Base Frequency:
Frekuensi dasar diubah dari 440 Hz (A4) menjadi 416.49 Hz, sehingga:
Nada dengan frekuensi 440 Hz berada di posisi ke-2 dalam 20-TET, bukan sebagai nada awal (A4).
2. Sistem Skala 20-TET:
Perhitungan frekuensi untuk 20 nada per oktaf, dengan 2 oktaf total (40 nada).
Perubahan Lain yang Terkait:
calculate_20_tet_frequencies:
Fungsi ini tetap menghitung frekuensi menggunakan rumus:
\text{frequency} = \text{base\_freq} \times (3^{\frac{n}{\text{notes\_per\_octave}}})
Gelombang Audio:
Nada dimainkan dengan gelombang sinus 16-bit signed pada 44.1 kHz.
File WAV:
Semua nada disimpan dalam file bernama 20_TET_2_Octaves.wav.
Output
1. Nada yang Dihasilkan:
Frekuensi nada dimulai dari 416.49 Hz untuk 20 nada dalam oktaf pertama, dilanjutkan dengan 20 nada dalam oktaf kedua.
Nada kedua memiliki frekuensi 440 Hz, sesuai dengan posisi dalam 20-TET.
2. File Audio:
File 20_TET_2_Octaves.wav menyimpan semua nada secara berurutan dengan durasi masing-masing 0.8 detik.
Catatan
Jika Anda ingin lebih memverifikasi posisi nada atau mengubah durasi tiap nada, Anda dapat memodifikasi variabel berikut:
Durasi Nada: Parameter duration pada fungsi play_tone.
Nama File: Parameter filename pada fungsi save_to_wav.
Kode Anda sangat baik untuk eksplorasi musik mikrotonal menggunakan skala 20-TET!
Bisakah kode tersebut diapplikasikan ke kode oemograman pembuatan keyboard digital, sehingga setiap tuts pada keyboard digital akan memakai frekwensi yang tepat sesuai nada masing-masing
Tentu, kode pembuatan nada dengan skala 20-TET dapat diaplikasikan ke kode program keyboard digital Anda dengan beberapa modifikasi. Berikut adalah langkah-langkah integrasi yang dapat dilakukan:
1. Tambahkan Fungsi generate_wave dan play_tone: Salin fungsi generate_wave, play_tone, dan calculate_20_tet_frequencies ke dalam file kode keyboard digital Anda. Pastikan pustaka NumPy dan wave telah diimpor.
2. Integrasi Nada ke Tombol Keyboard: Alih-alih memainkan file WAV yang telah disimpan, gunakan fungsi play_tone untuk menghasilkan nada berdasarkan frekuensi tertentu secara real-time.
3. Definisi Nada Skala 20-TET: Buat daftar frekuensi menggunakan fungsi calculate_20_tet_frequencies untuk menggantikan nada standar pada keyboard digital Anda.
Berikut adalah contoh kode yang telah dimodifikasi:
import numpy as np
import pygame
import wave
import tkinter as tk
from tkinter import Radiobutton, IntVar
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Fungsi untuk menghitung frekuensi 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=1):
frequencies = []
for octave in range(octaves):
for n in range(notes_per_octave):
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3))
base_freq *= 3 # Naik satu oktaf
return frequencies
# Fungsi untuk membuat gelombang nada
def generate_wave(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
return wave
# Fungsi untuk memainkan nada
def play_tone(frequency, duration, amplitude=0.5, sample_rate=44100):
wave_data = generate_wave(frequency, duration, amplitude, sample_rate)
sound = pygame.sndarray.make_sound(wave_data)
sound.play(-1) # Loop satu kali
pygame.time.delay(int(duration * 1000)) # Durasi dalam milidetik
sound.stop()
# Hitung frekuensi untuk skala 20-TET (2 oktaf)
frequencies = calculate_20_tet_frequencies(416.49, 20, octaves=2)
# Fungsi untuk memainkan nada berdasarkan indeks frekuensi
def play_sound_by_index(index):
if 0 <= index < len(frequencies):
play_tone(frequencies[index], duration=0.5) # Durasi 0,5 detik
# Inisialisasi UI
root = tk.Tk()
root.geometry("400x300")
root.title("Keyboard 20-TET")
# Variabel untuk menyimpan pilihan mode
play_mode = IntVar(value=1) # Default ke Nada Tunggal
# Radio button untuk memilih mode
frame_mode = tk.Frame(root)
frame_mode.pack(pady=10)
Radiobutton(frame_mode, text="Nada Tunggal", variable=play_mode, value=1).pack(side="left")
Radiobutton(frame_mode, text="Akord", variable=play_mode, value=2).pack(side="left")
# Tombol-tombol untuk memainkan nada
keys_frame = tk.Frame(root)
keys_frame.pack(pady=20)
# Buat tombol untuk setiap nada
for i in range(20): # 20 tombol untuk 20 nada dalam satu oktaf
btn = tk.Button(keys_frame, text=f"Key {i+1}", width=5,
command=lambda idx=i: play_sound_by_index(idx))
btn.grid(row=i // 5, column=i % 5, padx=5, pady=5)
# Jalankan aplikasi
root.mainloop()
Penjelasan:
1. Skala 20-TET: Frekuensi dihitung menggunakan basis 416.49 Hz (contoh nada dasar).
2. Pustaka NumPy dan Pygame: Digunakan untuk menghasilkan dan memainkan nada secara real-time.
3. Integrasi UI: Setiap tombol pada UI akan memanggil fungsi play_sound_by_index dengan indeks frekuensi.
Hasil:
Aplikasi keyboard digital Anda sekarang dapat memainkan nada dengan skala 20-TET untuk 2 oktaf secara langsung tanpa file WAV statis.
Bagaimana supaya wujud tampilan GUi nya berupa tuts tuts keyboard digital (bukan kotak kotak sepertti itu)
Untuk mengubah tampilan GUI menjadi berupa tuts keyboard digital, kita dapat memanfaatkan Canvas di tkinter untuk menggambar bentuk tuts seperti keyboard. Berikut langkah-langkah untuk mencapainya:
1. Gunakan Canvas untuk Desain Tuts Keyboard
Canvas memungkinkan kita menggambar elemen berbentuk bebas, seperti persegi panjang untuk tuts putih dan hitam pada keyboard digital.
2. Desain Tuts Keyboard
- Tuts putih: Gambar menggunakan create_rectangle dengan warna putih.
- Tuts hitam: Gambar menggunakan create_rectangle dengan warna hitam di atas tuts putih.
- Pastikan jarak antar-tuts sesuai dengan tata letak keyboard yang sebenarnya.
3. Respons Interaksi
-Tambahkan fitur interaktif pada tuts keyboard, seperti menampilkan nada saat tuts ditekan. Ini bisa dilakukan dengan menggunakan metode bind untuk menangkap event mouse klik.
Contoh Kode
Berikut adalah contoh implementasi sederhana untuk membuat tampilan keyboard digital dengan tuts piano:
import tkinter as tk
class DigitalKeyboard:
def __init__(self, root):
self.root = root
self.root.title("Keyboard Digital")
# Canvas untuk menggambar keyboard
self.canvas = tk.Canvas(root, width=700, height=300, bg="lightgrey")
self.canvas.pack()
# Gambar tuts putih
self.white_keys = []
for i in range(14): # 14 tuts putih
x1 = 10 + i * 50
y1 = 50
x2 = x1 + 40
y2 = y1 + 200
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="black", tags=f"white_{i}")
self.white_keys.append(key)
# Gambar tuts hitam
self.black_keys = []
black_positions = [0, 1, 3, 4, 5, 7, 8, 10, 11, 12] # Posisi tuts hitam
for i in black_positions:
x1 = 40 + i * 50
y1 = 50
x2 = x1 + 30
y2 = y1 + 120
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="black", outline="black", tags=f"black_{i}")
self.black_keys.append(key)
# Tambahkan interaksi
self.canvas.tag_bind("white", "<Button-1>", self.on_white_key_click)
self.canvas.tag_bind("black", "<Button-1>", self.on_black_key_click)
def on_white_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
print(f"White key pressed: {key_id}")
def on_black_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
print(f"Black key pressed: {key_id}")
# Jalankan aplikasi
root = tk.Tk()
keyboard = DigitalKeyboard(root)
root.mainloop()
Penjelasan Kode
1. Tuts Putih:
- Dibuat menggunakan create_rectangle dengan lebar tetap (40 piksel) dan posisi horizontal berulang (dengan jarak 50 piksel).
2. Tuts Hitam:
- Dibuat pada posisi tertentu di atas tuts putih.
- Lebarnya lebih kecil dari tuts putih, dan tingginya juga lebih pendek.
3. Interaksi:
- Setiap tuts memiliki tags untuk membedakan tuts putih (white) dan hitam (black).
- Event Button-1 menangkap klik pada tuts dan mencetak tuts yang ditekan.
Hasil
Tampilan GUI akan berupa keyboard dengan tuts putih dan hitam seperti piano digital. Anda dapat memperbaiki estetika lebih lanjut dengan menyesuaikan ukuran atau menambahkan animasi saat tuts ditekan.
Kode yang benar pembuatan tampilan GUI untuk keyboard digital musik sistem 12 TET (20 nada per oktaf) adalah berikut ini:
import tkinter as tk
class DigitalKeyboard12TET:
def __init__(self, root):
self.root = root
self.root.title("Keyboard Digital (12-TET, 20 Nada per Oktaf)")
# Canvas untuk menggambar keyboard
self.canvas = tk.Canvas(root, width=1500, height=300, bg="lightgrey")
self.canvas.pack()
# Gambar tuts putih (20 nada total per oktaf termasuk tuts hitam)
self.white_keys = []
num_keys = 33 # Total nada dalam 3 oktaf
for i in range(num_keys): # Menggambar 33 tuts putih
x1 = 10 + i * 40
y1 = 50
x2 = x1 + 30
y2 = y1 + 155
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="black", tags=f"white_{i}")
self.white_keys.append(key)
# Posisi tuts hitam sesuai dengan 12-TET dengan 20 nada
self.black_keys = []
black_positions = [0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 19, 20, 22, 23, 24, 25, 27, 28, 29, 30, 31 ] # Indeks posisi nada hitam
for i in black_positions:
x1 = 35 + i * 40 # Posisi lebih kecil untuk hitam
y1 = 50
x2 = x1 + 20
y2 = y1 + 80
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="black", outline="black", tags=f"black_{i}")
self.black_keys.append(key)
# Tambahkan interaksi
self.canvas.tag_bind("white", "<Button-1>", self.on_white_key_click)
self.canvas.tag_bind("black", "<Button-1>", self.on_black_key_click)
def on_white_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
print(f"White key pressed: {key_id}")
def on_black_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
print(f"Black key pressed: {key_id}")
# Jalankan aplikasi
root = tk.Tk()
keyboard = DigitalKeyboard12TET(root)
root.mainloop()
Dalam sistem 12-TET (12 Tone Equal Temperament) dengan 20 nada per oktaf, distribusi tuts hitam akan berbeda karena jumlah nada hitam (dan putih) bertambah. Untuk merepresentasikan ini, kita akan menyesuaikan posisi dan jumlah tuts hitam agar sesuai dengan sistem tersebut.
Penjelasan Perubahan
1. Tuts Putih:
- Jumlah total tuts per oktaf (termasuk nada putih dan hitam) adalah 20.
- Setiap tuts putih memiliki lebar 30 piksel, dan jarak antar-tuts adalah 40 piksel.
2. Tuts Hitam:
- Posisi nada hitam mengikuti pola 12-TET, namun diubah untuk mencakup 20 nada.
- Pola hitam: Nada ke-1, ke-2, ke-3, ke-4, ke-6, ke-7, ke-8, ke-9, ke-10, dst., sesuai dengan urutan dalam sistem.
3. Interaksi:
Sama seperti sebelumnya, klik pada tuts akan mencetak tuts yang ditekan.
Distribusi Nada
Dalam 12-TET (20 nada per oktaf), pola tuts hitam di atas mencerminkan urutan frekuensi yang lebih rapat dibandingkan piano standar.
Visualisasi
Hasilnya akan berupa:
- Dalam 3 oktaf, tuts putih berjumlah 33 tuts (11 per oktaf), masing-masing dengan ukuran sama.
- Dalam 3 oktaf, tuts hitam berjumlah 27 tuts (9 per oktaf), tuts hitam berada di atas tuts putih sesuai pola Nada ke-1, ke-2, ke-3, ke-4, ke-6, ke-7, ke-8, ke-9, ke-10, dst.,
Jika ada penyesuaian lebih lanjut pada tata letak tuts, silakan beri tahu!
Selanjutnya tolong ditandai setiap tuts dengan nada yang benar dimulai dari tuts putih pertama = E3, tuts hitam pertama = E#3, dan seterusnya mengikuti susunan nada musik sistem 12 TET (20 nada per oktaf) : E3, E#3, F3, F#3, G3, G#3, H3, H#3, I3, J3, J#3, K3, K#3, A3, A#3, B3, B#3, C4, C#3, D3, E4, E#4, F4, F#4, G4, G#4, H4, H#4, I4, J4, J#4, K4, K#4, A4, A#4, B4, B#4, C4, C#4, D4, E5, E#5, F5, F#5, G5, G#5, H5, H#5, I5, J5, J#5, K5, K#5, A5, A#5, B5, B#5, C5, C#5, D5.
Untuk menambahkan label nama nada pada setiap tuts, kita dapat memperbarui kode Anda dengan menambahkan teks di atas setiap tuts pada posisi yang sesuai.
Berikut adalah kode yang dimodifikasi untuk menampilkan label nada yang sesuai pada setiap tuts berdasarkan susunan nada dalam sistem 12-TET (20 nada per oktaf). Kode ini akan menggambar tuts putih dan hitam, serta memberi label nada pada setiap tuts.
Kode Modifikasi
import tkinter as tk
class DigitalKeyboard12TET:
def __init__(self, root):
self.root = root
self.root.title("Keyboard Digital (12-TET, 20 Nada per Oktaf)")
# Canvas untuk menggambar keyboard
self.canvas = tk.Canvas(root, width=1500, height=400, bg="lightgrey")
self.canvas.pack()
# Susunan nada dalam sistem 12-TET (20 nada per oktaf)
self.notes = [
"E", "E#", "F", "F#", "G", "G#", "H", "H#", "I", "J", "J#", "K", "K#", "A", "A#", "B", "B#", "C", "C#", "D"
]
# Menggambar tuts putih
self.white_keys = []
num_white_keys = 33 # Total tuts putih untuk menutupi beberapa oktaf
start_octave = 3 # Dimulai dari oktaf 3
note_index = 0 # Indeks awal untuk catatan nada
for i in range(num_white_keys):
x1 = 10 + i * 40
y1 = 50
x2 = x1 + 30
y2 = y1 + 155
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="black", tags=f"white_{i}")
self.white_keys.append(key)
# Menambahkan label pada tuts putih
note_label = f"{self.notes[note_index % len(self.notes)]}{start_octave + (note_index // len(self.notes))}"
self.canvas.create_text((x1 + x2) / 2, y2 + 10, text=note_label, font=("Arial", 10))
note_index += 1
# Posisi tuts hitam dalam sistem 12-TET (20 nada per oktaf)
self.black_keys = []
black_positions = [
0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 19, 20, 22, 23, 24, 25, 27, 28, 29, 30, 31
] # Posisi relatif terhadap tuts putih
black_note_index = 0 # Indeks awal untuk nada hitam
for i in black_positions:
x1 = 35 + i * 40
y1 = 50
x2 = x1 + 20
y2 = y1 + 80
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="black", outline="black", tags=f"black_{i}")
self.black_keys.append(key)
# Menambahkan label pada tuts hitam
note_label = f"{self.notes[black_note_index % len(self.notes)]}{start_octave + (black_note_index // len(self.notes))}"
self.canvas.create_text((x1 + x2) / 2, y2 + 15, text=note_label, fill="white", font=("Arial", 8))
black_note_index += 1
# Tambahkan interaksi
self.canvas.tag_bind("white", "<Button-1>", self.on_white_key_click)
self.canvas.tag_bind("black", "<Button-1>", self.on_black_key_click)
def on_white_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
print(f"White key pressed: {key_id}")
def on_black_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
print(f"Black key pressed: {key_id}")
# Jalankan aplikasi
root = tk.Tk()
keyboard = DigitalKeyboard12TET(root)
root.mainloop()
Penjelasan Perubahan
1. Penambahan Label Nada:
- Teks ditambahkan menggunakan create_text pada setiap tuts putih dan hitam.
- Nada putih menggunakan daftar white_notes (tanpa #), sedangkan nada hitam menggunakan black_notes (dengan #).
- Posisi teks disesuaikan agar berada di bawah setiap tuts.
2. Rentang Oktaf:
- Ditambahkan tiga oktaf: 3, 4, dan 5.
- Setiap oktaf memiliki 20 nada sesuai sistem 12-TET.
3. Penyesuaian Posisi Tuts Hitam:
Posisi tuts hitam mengikuti pola indeks dalam black_positions.
4. Ukuran Canvas:
Lebar kanvas diperbesar agar bisa memuat lebih banyak tuts.
Hasil
- Tuts putih dan hitam ditampilkan dengan label nada yang benar, dimulai dari E3 hingga D5.
Anda dapat menyesuaikan rentang oktaf dengan memperluas daftar self.octaves.
Jika ada yang ingin diperbaiki lebih lanjut, silakan beri tahu!
Penjelasan Kode:
1. Label Nada pada Tuts Putih:
- Menggunakan array notes untuk menampilkan nada sesuai dengan sistem 12-TET.
- Label dihitung berdasarkan indeks dan ditambahkan pada posisi bawah tuts putih.
2. Label Nada pada Tuts Hitam:
- Posisi hitam ditentukan berdasarkan array black_positions.
- Label dihitung dengan cara yang sama, tetapi diletakkan di bawah tuts hitam dengan warna teks putih.
3. Interaksi:
- Klik pada tuts putih atau hitam memanggil fungsi yang mencetak tuts yang ditekan.
- Kode ini akan menggambar tuts piano dengan nada sesuai sistem 12-TET (20 nada per oktaf) dan memberikan label pada setiap tutsnya.
Label nada pada setiap tuts seharusnya pakai font yang kecil (ukuran font= 4). Label nada pada setiap tuts putih adalah: "E", "F", "G", "H", "I", "J", "K", "A", "B", "C", "D" , dan label nada pada setiap tuts hitam adalah: "E#", "F#", "G#", "H#", "J#", "K#", "A#", "B#", "C#"
Font pada tkinter tidak memiliki ukuran numerik langsung seperti font=4, tetapi kita dapat mengatur ukuran font dengan parameter tuple (nama_font, ukuran, opsi). Untuk menghasilkan font kecil, kita cukup menetapkan ukuran font ke angka kecil, misalnya font 4 untuk tuts putih, dan font 3 untuk tuts hitam.
Berikut adalah kode yang dimodifikasi untuk menggunakan font kecil untuk label nada:
import tkinter as tk
class DigitalKeyboard12TET:
def __init__(self, root):
self.root = root
self.root.title("Keyboard Digital (12-TET, 20 Nada per Oktaf)")
# Canvas untuk menggambar keyboard
self.canvas = tk.Canvas(root, width=1350, height=400, bg="lightgrey")
self.canvas.pack()
# Susunan nada untuk tuts putih dan hitam
white_notes = ["E", "F", "G", "H", "I", "J", "K", "A", "B", "C", "D"]
black_notes = ["E#", "F#", "G#", "H#", "J#", "K#", "A#", "B#", "C#"]
# Menggambar tuts putih
self.white_keys = []
num_white_keys = 33 # Total tuts putih (untuk tiga oktaf)
start_octave = 3 # Dimulai dari oktaf 3
for i in range(num_white_keys):
x1 = 10 + i * 40
y1 = 50
x2 = x1 + 30
y2 = y1 + 155
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="black", tags=f"white_{i}")
self.white_keys.append(key)
# Menambahkan label pada tuts putih
note_label = f"{white_notes[i % len(white_notes)]}{start_octave + (i // len(white_notes))}"
self.canvas.create_text((x1 + x2) / 2, y2 + 10, text=note_label, font=("Arial", 4))
# Menggambar tuts hitam
self.black_keys = []
black_positions = [0, 1, 2, 3, 5, 6, 7, 8, 9] # Posisi relatif terhadap tuts putih per oktaf
num_black_keys_per_octave = len(black_positions)
num_octaves = 3 # Jumlah oktaf
for octave in range(num_octaves):
for i, position in enumerate(black_positions):
x1 = 35 + (position + octave * len(white_notes)) * 40
y1 = 50
x2 = x1 + 20
y2 = y1 + 80
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="black", outline="black", tags=f"black_{i + octave * num_black_keys_per_octave}")
self.black_keys.append(key)
# Menambahkan label pada tuts hitam
note_label = f"{black_notes[i]}{start_octave + octave}"
self.canvas.create_text((x1 + x2) / 2, y2 - 10, text=note_label, fill="white", font=("Arial", 3))
# Tambahkan interaksi
self.canvas.tag_bind("white", "<Button-1>", self.on_white_key_click)
self.canvas.tag_bind("black", "<Button-1>", self.on_black_key_click)
def on_white_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
print(f"White key pressed: {key_id}")
def on_black_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
print(f"Black key pressed: {key_id}")
# Jalankan aplikasi
root = tk.Tk()
keyboard = DigitalKeyboard12TET(root)
root.mainloop()
Modifikasi Utama:
1. Ukuran Font Kecil:
- Pada label tuts putih: font=("Arial", 4)
- Pada label tuts hitam: font=("Arial", 3)
2. Efek Ukuran Font:
Ukuran font kecil memastikan label tidak terlalu besar dibandingkan dengan ukuran tuts.
Kode ini akan menampilkan label nada yang kecil dan sesuai pada setiap tuts. Silakan coba dan sesuaikan jika dibutuhkan.
Penjelasan:
1. Label Tuts Putih:
- Nada mengikuti pola: ["E", "F", "G", "H", "I", "J", "K", "A", "B", "C", "D"]
- Ditambahkan oktav mulai dari oktav 3.
2. Label Tuts Hitam:
- Nada mengikuti pola: ["E#", "F#", "G#", "H#", "J#", "K#", "A#", "B#", "C#"]
- Ditambahkan oktav mulai dari oktav 3.
3. Posisi Tuts Hitam:
Diletakkan di atas tuts putih pada posisi tertentu, sesuai dengan urutan dalam sistem 12-TET.
4. Font Kecil:
Digunakan font=("Arial", 5) untuk memastikan label tetap kecil dan tidak mengganggu visual tuts.
Silakan dicoba! Layout ini akan menghasilkan keyboard digital sesuai dengan deskripsi Anda.
Perhitungan nilai label setiap tuts hitam untuk oktaf yang sesuai:
Penempatan dan pelabelan tuts hitam untuk oktaf ke-3, oktaf ke-4 dan ke-5 telah memiliki nilai yang benar sesuai dengan oktavnya, di mana tuts hitam oktaf ke-3, oktaf ke-4, dan oktaf ke-5 telah digambar dengan benar, dan label nada sesuai dengan oktaf masing-masing.
1. Pengaturan Tuts Hitam untuk Setiap Oktaf:
- Loop menggambar tuts hitam dilakukan berdasarkan jumlah oktaf (num_octaves).
- Setiap tuts hitam digambar pada posisi yang sesuai dalam oktaf berdasarkan black_positions.
2. Pelabelan Oktaf pada Tuts Hitam:
Label note_label kini mempertimbangkan octave secara eksplisit, sehingga label untuk setiap oktaf ditampilkan dengan benar.
3. Koreksi Oktaf:
Oktaf dihitung menggunakan start_octave + octave untuk memastikan label nada sesuai.
4. Perhitungan Posisi:
Posisi tuts hitam (x1) disesuaikan dengan posisi relatif dalam oktaf dan total jumlah tuts putih.
Hasil:
- Tuts hitam oktaf ke-3, ke-4, dan ke-5 digambar dengan benar.
- Label pada tuts hitam diperbaiki:
Oktaf ke-3: E#3, F#3, G#3, H#3, J#3, K#3, A#3, B#3, C#3.
Oktaf ke-4: E#4, F#4, G#4, H#4, J#4, K#4, A#4, B#4, C#4.
Oktaf ke-5: E#5, F#5, G#5, H#5, J#5, K#5, A#5, B#5, C#5.
Jika ada hal lain yang ingin diperbaiki, beri tahu saya!
Tolong gabungkan kode pemograman "keyboard digital" berikut:
import tkinter as tk
class DigitalKeyboard12TET:
def __init__(self, root):
self.root = root
self.root.title("Keyboard Digital (12-TET, 20 Nada per Oktaf)")
# Canvas untuk menggambar keyboard
self.canvas = tk.Canvas(root, width=1350, height=400, bg="lightgrey")
self.canvas.pack()
# Susunan nada untuk tuts putih dan hitam
white_notes = ["E", "F", "G", "H", "I", "J", "K", "A", "B", "C", "D"]
black_notes = ["E#", "F#", "G#", "H#", "J#", "K#", "A#", "B#", "C#"]
# Menggambar tuts putih
self.white_keys = []
num_white_keys = 33 # Total tuts putih (untuk tiga oktaf)
start_octave = 3 # Dimulai dari oktaf 3
for i in range(num_white_keys):
x1 = 10 + i * 40
y1 = 50
x2 = x1 + 30
y2 = y1 + 155
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="black", tags=f"white_{i}")
self.white_keys.append(key)
# Menambahkan label pada tuts putih
note_label = f"{white_notes[i % len(white_notes)]}{start_octave + (i // len(white_notes))}"
self.canvas.create_text((x1 + x2) / 2, y2 + 10, text=note_label, font=("Arial", 4))
# Menggambar tuts hitam
self.black_keys = []
black_positions = [0, 1, 2, 3, 5, 6, 7, 8, 9] # Posisi relatif terhadap tuts putih per oktaf
num_black_keys_per_octave = len(black_positions)
num_octaves = 3 # Jumlah oktaf
for octave in range(num_octaves):
for i, position in enumerate(black_positions):
x1 = 35 + (position + octave * len(white_notes)) * 40
y1 = 50
x2 = x1 + 20
y2 = y1 + 80
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="black", outline="black", tags=f"black_{i + octave * num_black_keys_per_octave}")
self.black_keys.append(key)
# Menambahkan label pada tuts hitam
note_label = f"{black_notes[i]}{start_octave + octave}"
self.canvas.create_text((x1 + x2) / 2, y2 - 10, text=note_label, fill="white", font=("Arial", 3))
# Tambahkan interaksi
self.canvas.tag_bind("white", "<Button-1>", self.on_white_key_click)
self.canvas.tag_bind("black", "<Button-1>", self.on_black_key_click)
def on_white_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
print(f"White key pressed: {key_id}")
def on_black_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
print(f"Black key pressed: {key_id}")
# Jalankan aplikasi
root = tk.Tk()
keyboard = DigitalKeyboard12TET(root)
root.mainloop()
Dengan kode pemograman "audio generator" berikut ini (dimana setiap tuts memiliki fungsi callback untuk memainkan nada, dan nada A3 = A4 / 3 = 416,49 / 3):
import numpy as np
import pygame
import wave
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Fungsi untuk menghitung frekuensi 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=1):
frequencies = []
for octave in range(octaves):
for n in range(notes_per_octave):
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3))
base_freq *= 3 # Naik satu oktaf
return frequencies
# Fungsi untuk membuat gelombang nada
def generate_wave(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
return wave
# Fungsi untuk menyimpan gelombang ke file WAV
def save_to_wav(filename, wave_data, sample_rate=44100):
with wave.open(filename, 'w') as wav_file:
wav_file.setnchannels(1) # Mono
wav_file.setsampwidth(2) # 16-bit
wav_file.setframerate(sample_rate)
wav_file.writeframes(wave_data.tobytes())
# Fungsi untuk memainkan nada
def play_tone(frequency, duration, amplitude=0.5, sample_rate=44100):
wave_data = generate_wave(frequency, duration, amplitude, sample_rate)
sound = pygame.sndarray.make_sound(wave_data)
sound.play(-1) # Loop satu kali
pygame.time.delay(int(duration * 1000)) # Durasi dalam milidetik
sound.stop()
return wave_data
# Hitung frekuensi untuk 2 oktaf
frequencies = calculate_20_tet_frequencies(416.49/3, 20, octaves=3)
# Buffer untuk menyimpan semua gelombang suara
all_waves = []
# Mainkan nada satu per satu dan tambahkan ke buffer WAV
for freq in frequencies:
print(f"Playing {freq} Hz")
wave_data = play_tone(freq, duration=0.8) # Mainkan nada
all_waves.append(wave_data)
# Gabungkan semua gelombang menjadi satu
final_wave = np.concatenate(all_waves)
# Simpan ke file WAV
save_to_wav("20_TET_2_Octaves.wav", final_wave)
print("File 20_TET_2_Octaves.wav berhasil dibuat!")
Berikut adalah penggabungan dari kedua kode, sehingga setiap tuts pada "keyboard digital" dapat memainkan nada sesuai dengan "audio generator" 20-TET:
Kode Gabungan
import tkinter as tk
import numpy as np
import pygame
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Fungsi untuk menghitung frekuensi 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=1):
frequencies = []
for octave in range(octaves):
for n in range(notes_per_octave):
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3))
base_freq *= 3 # Naik satu oktaf
return frequencies
# Fungsi untuk membuat gelombang nada
def generate_wave(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
return wave
# Fungsi untuk memainkan nada
def play_tone(frequency, duration, amplitude=0.5, sample_rate=44100):
wave_data = generate_wave(frequency, duration, amplitude, sample_rate)
sound = pygame.sndarray.make_sound(wave_data)
sound.play(-1) # Mainkan nada
pygame.time.delay(int(duration * 1000)) # Durasi dalam milidetik
sound.stop()
# Hitung frekuensi untuk 3 oktaf (20-TET)
frequencies = calculate_20_tet_frequencies(416.49 / 3, 20, octaves=3)
# Class untuk keyboard digital
class DigitalKeyboard20TET:
def __init__(self, root):
self.root = root
self.root.title("Keyboard Digital (20-TET, 20 Nada per Oktaf)")
# Canvas untuk menggambar keyboard
self.canvas = tk.Canvas(root, width=1350, height=400, bg="lightgrey")
self.canvas.pack()
# Susunan nada untuk tuts putih dan hitam
white_notes = ["E", "F", "G", "H", "I", "J", "K", "A", "B", "C", "D"]
black_notes = ["E#", "F#", "G#", "H#", "J#", "K#", "A#", "B#", "C#"]
# Menggambar tuts putih
self.white_keys = []
self.note_labels = [] # Label nada yang terkait
num_white_keys = 33 # Total tuts putih (untuk tiga oktaf)
start_octave = 3 # Dimulai dari oktaf 3
for i in range(num_white_keys):
x1 = 10 + i * 40
y1 = 50
x2 = x1 + 30
y2 = y1 + 155
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="black", tags=f"white_{i}")
self.white_keys.append(key)
# Menambahkan label pada tuts putih
note_label = f"{white_notes[i % len(white_notes)]}{start_octave + (i // len(white_notes))}"
self.note_labels.append(note_label)
self.canvas.create_text((x1 + x2) / 2, y2 + 10, text=note_label, font=("Arial", 5))
# Menggambar tuts hitam
self.black_keys = []
black_positions = [0, 1, 2, 3, 5, 6, 7, 8, 9] # Posisi relatif terhadap tuts putih per oktaf
num_black_keys_per_octave = len(black_positions)
num_octaves = 3 # Jumlah oktaf
for octave in range(num_octaves):
for i, position in enumerate(black_positions):
x1 = 35 + (position + octave * len(white_notes)) * 40
y1 = 50
x2 = x1 + 20
y2 = y1 + 80
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="black", outline="black", tags=f"black_{i + octave * num_black_keys_per_octave}")
self.black_keys.append(key)
# Menambahkan label pada tuts hitam
note_label = f"{black_notes[i]}{start_octave + octave}"
self.note_labels.append(note_label)
self.canvas.create_text((x1 + x2) / 2, y2 - 10, text=note_label, fill="white", font=("Arial", 3))
# Tambahkan interaksi
self.canvas.tag_bind("white", "<Button-1>", self.on_white_key_click)
self.canvas.tag_bind("black", "<Button-1>", self.on_black_key_click)
def on_white_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
index = self.white_keys.index(key_id[0])
freq = frequencies[index]
print(f"White key pressed: {self.note_labels[index]}, Frequency: {freq} Hz")
play_tone(freq, duration=0.8)
def on_black_key_click(self, event):
key_id = self.canvas.find_closest(event.x, event.y)
index = self.black_keys.index(key_id[0])
freq = frequencies[len(self.white_keys) + index]
print(f"Black key pressed: {self.note_labels[len(self.white_keys) + index]}, Frequency: {freq} Hz")
play_tone(freq, duration=0.8)
# Jalankan aplikasi
root = tk.Tk()
keyboard = DigitalKeyboard20TET(root)
root.mainloop()
Penjelasan
1. Integrasi Suara: Nada setiap tuts akan memainkan frekuensi 20-TET yang dihitung menggunakan calculate_20_tet_frequencies.
2. Event Binding: Klik pada tuts putih atau hitam akan memanggil fungsi play_tone dengan frekuensi yang sesuai.
3. Label Nada: Setiap tuts putih dan hitam diberi label sesuai urutan nada.
4. Audio Callback: Menggunakan pygame untuk memutar suara dengan gelombang sinusoidal.
Silakan coba jalankan kode ini untuk menguji integrasi antara visualisasi keyboard dan audio generator.
Kenapa ketika setiap tuts, baik tuts putih maupun tuts hitam ditekan, maka belum mengeluarkan suara (bunyi) nada
Masalah utama mengapa tuts belum mengeluarkan suara adalah karena kode keyboard digital dan audio generator belum terhubung secara langsung. Fungsi callback untuk memutar nada belum ditambahkan ke tuts pada keyboard digital. Selain itu, beberapa langkah pengintegrasian juga harus dilakukan, seperti:
1. Menghubungkan setiap tuts dengan frekuensi nada: Setiap tuts harus memiliki nada tertentu yang dapat diputar ketika ditekan.
2. Menggunakan play_tone dari kode audio generator: Fungsi ini harus dipanggil saat tuts ditekan untuk memutar nada yang sesuai.
Berikut adalah modifikasi kode lengkap setelah mengintegrasikan keyboard digital dan audio generator:
Kode Terintegrasi
import tkinter as tk
import numpy as np
import pygame
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Fungsi untuk menghitung frekuensi 20-TET
def calculate_20_tet_frequencies(base_freq, notes_per_octave, octaves=1):
frequencies = []
for octave in range(octaves):
for n in range(notes_per_octave):
freq = base_freq * (3 ** (n / notes_per_octave))
frequencies.append(round(freq, 3))
base_freq *= 3 # Naik satu oktaf
return frequencies
# Fungsi untuk membuat gelombang nada
def generate_wave(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
return wave
# Fungsi untuk memainkan nada
def play_tone(frequency, duration=0.5, amplitude=0.5, sample_rate=44100):
wave_data = generate_wave(frequency, duration, amplitude, sample_rate)
sound = pygame.sndarray.make_sound(wave_data)
sound.play(-1) # Loop satu kali
pygame.time.delay(int(duration * 1000)) # Durasi dalam milidetik
sound.stop()
# Menghitung frekuensi untuk 3 oktaf
frequencies = calculate_20_tet_frequencies(416.49 / 3, 20, octaves=3)
# Class untuk Keyboard Digital
class DigitalKeyboard12TET:
def __init__(self, root):
self.root = root
self.root.title("Keyboard Digital (12-TET, 20 Nada per Oktaf)")
# Canvas untuk menggambar keyboard
self.canvas = tk.Canvas(root, width=1350, height=400, bg="lightgrey")
self.canvas.pack()
# Susunan nada untuk tuts putih dan hitam
white_notes = ["E", "F", "G", "H", "I", "J", "K", "A", "B", "C", "D"]
black_notes = ["E#", "F#", "G#", "H#", "J#", "K#", "A#", "B#", "C#"]
# Menggambar tuts putih
self.white_keys = []
num_white_keys = 33 # Total tuts putih (untuk tiga oktaf)
start_octave = 3 # Dimulai dari oktaf 3
for i in range(num_white_keys):
x1 = 10 + i * 40
y1 = 50
x2 = x1 + 30
y2 = y1 + 155
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="black", tags=f"white_{i}")
self.white_keys.append(key)
# Menambahkan label pada tuts putih
note_label = f"{white_notes[i % len(white_notes)]}{start_octave + (i // len(white_notes))}"
self.canvas.create_text((x1 + x2) / 2, y2 + 10, text=note_label, font=("Arial", 5))
# Hubungkan tuts dengan frekuensi nada
freq = frequencies[i % len(frequencies)] # Frekuensi untuk tuts putih
self.canvas.tag_bind(f"white_{i}", "<Button-1>", lambda event, f=freq: self.on_key_click(f))
# Menggambar tuts hitam
self.black_keys = []
black_positions = [0, 1, 2, 3, 5, 6, 7, 8, 9] # Posisi relatif terhadap tuts putih per oktaf
num_black_keys_per_octave = len(black_positions)
num_octaves = 3 # Jumlah oktaf
for octave in range(num_octaves):
for i, position in enumerate(black_positions):
x1 = 35 + (position + octave * len(white_notes)) * 40
y1 = 50
x2 = x1 + 20
y2 = y1 + 80
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="black", outline="black", tags=f"black_{i + octave * num_black_keys_per_octave}")
self.black_keys.append(key)
# Menambahkan label pada tuts hitam
note_label = f"{black_notes[i]}{start_octave + octave}"
self.canvas.create_text((x1 + x2) / 2, y2 - 10, text=note_label, fill="white", font=("Arial", 3))
# Hubungkan tuts dengan frekuensi nada
freq_index = len(white_notes) + i + octave * num_black_keys_per_octave
if freq_index < len(frequencies):
freq = frequencies[freq_index] # Frekuensi untuk tuts hitam
self.canvas.tag_bind(f"black_{i + octave * num_black_keys_per_octave}", "<Button-1>", lambda event, f=freq: self.on_key_click(f))
def on_key_click(self, frequency):
# Mainkan nada sesuai dengan frekuensi
play_tone(frequency)
print(f"Key pressed, frequency: {frequency} Hz")
# Jalankan aplikasi
root = tk.Tk()
keyboard = DigitalKeyboard12TET(root)
root.mainloop()
Penjelasan Modifikasi
1. Frekuensi Nada:
- Frekuensi nada dihitung menggunakan calculate_20_tet_frequencies untuk 3 oktaf.
- Setiap tuts putih dan hitam diberi frekuensi sesuai posisinya.
2. Fungsi Callback:
Fungsi on_key_click dipanggil ketika tuts ditekan, yang memainkan nada dengan frekuensi sesuai.
3. Interaksi dengan pygame:
play_tone digunakan untuk memutar nada saat tuts ditekan.
Hasil
Setelah menjalankan kode ini, setiap tuts (baik putih maupun hitam) akan mengeluarkan bunyi nada sesuai frekuensinya ketika ditekan.
Bunyi nada nada di tuts putih maupun tuts hitam masih salah. Semua bunyi frekwensi nada sudah ada di situ, tapi ada salah penempatan frekwensi nada pada tuts-tuts.
Masalah ini muncul karena pengaturan frekuensi pada setiap tuts belum disesuaikan dengan perubahan logika pengelompokan nada yang Anda sebutkan. Untuk memperbaikinya, kita harus mengubah asosiasi tuts dengan frekuensi nada yang benar sesuai permintaan.
Berikut adalah langkah perbaikannya:
1. Mapping Nada ke Frekuensi Baru: Kita buat daftar baru yang memetakan posisi tuts (putih dan hitam) ke frekuensi yang benar, seperti yang Anda jelaskan.
2. Memodifikasi Daftar Frekuensi: Setiap tuts diberi frekuensi sesuai nada baru yang sudah Anda tentukan.
Berikut kode lengkap setelah perbaikan:
Kode Perbaikan
import tkinter as tk
import numpy as np
import pygame
# Inisialisasi pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
# Frekuensi nada
frequencies_map = {
"E3": 67.975, "E#3": 71.813, "F3": 75.866, "F#3": 80.153, "G3": 84.68, "G#3": 89.462,
"H3": 94.512, "H#3": 99.846, "I3": 105.488, "J3": 111.442, "J#3": 117.734, "K3": 124.383,
"K#3": 131.41, "A3": 138.83, "A#3": 146.67, "B3": 154.953, "B#3": 163.693, "C3": 172.933,
"C#3": 182.103, "D3": 193.028,
"E4": 203.925, "E#4": 215.439, "F4": 227.597, "F#4": 240.46, "G4": 254.041, "G#4": 268.385,
"H4": 283.536, "H#4": 299.537, "I4": 316.463, "J4": 334.327, "J#4": 353.203, "K4": 373.149,
"K#4": 394.23, "A4": 416.49, "A#4": 440.00, "B4": 464.86, "B#4": 491.08, "C4": 518.80,
"C#4": 548.108, "D4": 579.084,
"E5": 611.776, "E#5": 646.316, "F5": 682.792, "F#5": 721.38, "G5": 762.124, "G#5": 805.156,
"H5": 850.608, "H#5": 898.612, "I5": 949.388, "J5": 1002.98, "J#5": 1059.608, "K5": 1119.448,
"K#5": 1182.676, "A5": 1249.468, "A#5": 1320.00, "B5": 1394.58, "B#5": 1473.24, "C5": 1556.40,
"C#5": 1644.324, "D5": 1737.252
}
# Fungsi untuk membuat gelombang nada
def generate_wave(frequency, duration, amplitude=0.5, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = (amplitude * np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)
return wave
# Fungsi untuk memainkan nada
def play_tone(frequency, duration=0.5, amplitude=0.5, sample_rate=44100):
wave_data = generate_wave(frequency, duration, amplitude, sample_rate)
sound = pygame.sndarray.make_sound(wave_data)
sound.play(-1)
pygame.time.delay(int(duration * 1000))
sound.stop()
# Class untuk Keyboard Digital
class DigitalKeyboard12TET:
def __init__(self, root):
self.root = root
self.root.title("Keyboard Digital (Mapping Nada)")
# Canvas untuk menggambar keyboard
self.canvas = tk.Canvas(root, width=1400, height=400, bg="lightgrey")
self.canvas.pack()
# Susunan nada untuk tuts putih dan hitam dalam tiga oktaf
white_notes = ['E', 'F', 'G', 'H', 'I', 'J', 'K', 'A', 'B', 'C', 'D']
black_notes = ["E#", "F#", "G#", "H#", "J#", "K#", "A#", "B#", "C#"]
octaves = [3, 4, 5]
# Menggambar tuts putih
self.white_keys = []
num_white_keys = len(white_notes) * len(octaves)
for i in range(num_white_keys):
x1 = 10 + i * 40
y1 = 50
x2 = x1 + 30
y2 = y1 + 155
octave = octaves[i // len(white_notes)]
note = f"{white_notes[i % len(white_notes)]}{octave}"
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="white", outline="black", tags=f"white_{i}")
self.white_keys.append(key)
self.canvas.create_text((x1 + x2) / 2, y2 + 10, text=note, font=("Arial", 5))
freq = frequencies_map.get(note, 0)
self.canvas.tag_bind(f"white_{i}", "<Button-1>", lambda event, f=freq: self.on_key_click(f))
# Menggambar tuts hitam
self.black_keys = []
black_positions = [0, 1, 2, 3, 5, 6, 7, 8, 9]
for i in range(num_white_keys // len(white_notes) * len(black_positions)):
octave_offset = i // len(black_positions)
position = black_positions[i % len(black_positions)] + octave_offset * len(white_notes)
if position < num_white_keys:
x1 = 35 + position * 40
y1 = 50
x2 = x1 + 20
y2 = y1 + 85
octave = octaves[octave_offset]
note = f"{black_notes[i % len(black_notes)]}{octave}"
key = self.canvas.create_rectangle(x1, y1, x2, y2, fill="black", outline="black", tags=f"black_{i}")
self.black_keys.append(key)
self.canvas.create_text((x1 + x2) / 2, y2 - 10, text=note, fill="white", font=("Arial", 3))
freq = frequencies_map.get(note, 0)
self.canvas.tag_bind(f"black_{i}", "<Button-1>", lambda event, f=freq: self.on_key_click(f))
def on_key_click(self, frequency):
play_tone(frequency)
print(f"Key pressed, frequency: {frequency} Hz")
# Jalankan aplikasi
root = tk.Tk()
keyboard = DigitalKeyboard12TET(root)
root.mainloop()
Perubahan yang Dilakukan
1. Frekuensi:
Setiap nada pada frequencies_map diatur sesuai logika baru yang Anda minta.
Frekuensi dipetakan ke nama tuts putih dan hitam secara eksplisit.
2. Penyesuaian Nada:
- white_notes dan black_notes berisi nama nada sesuai permintaan Anda.
- Tuts diberi label berdasarkan nada ini.
3. Interaksi Tuts dan Frekuensi:
Setiap tuts (baik putih maupun hitam) dipetakan langsung ke frekuensi dari frequencies_map.
Hasil
Ketika kode ini dijalankan, setiap tuts (baik putih maupun hitam) akan mengeluarkan bunyi nada yang sudah sesuai logika nada baru yang Anda minta.
Penjelasan tambahan
Telah dilakukan perbaikan kode untuk memastikan bahwa tuts hitam ditampilkan di semua oktaf (ke-3, ke-4 dan ke-5) dengan label yang benar:
1. Penyesuaian total jumlah tuts putih dan hitam agar mencakup semua oktaf.
2. Penyesuaian posisi relatif tuts hitam berdasarkan setiap oktaf.
3. Label untuk setiap tuts disesuaikan agar dinamis sesuai urutan oktaf dan nada.
4. Tuts Hitam: Ditampilkan untuk semua oktaf yang relevan (3–5).
5. Label Tuts: Disesuaikan agar sesuai dengan nama nada dan oktaf.
6. Posisi Hitam: Diperbaiki untuk menyesuaikan posisi relatif dengan tuts putih.
Telah diUji coba dan semua tuts serta bunyi nada sudah sesuai.
- Posisi tuts hitam dengan berpola [0, 1, 2, 3, 5, 6, 7, 8, 9], serta labelnya ditampilkan dengan benar pada semua tuts.
1. Polanya: Hitam mengikuti indeks black_positions = [0, 1, 2, 3, 5, 6, 7, 8, 9] untuk setiap oktaf.
2. Label tuts hitam: Ditampilkan dengan font yang sesuai.
3. Frekuensi aman: Semua nada yang tidak ditemukan dalam frequencies_map akan mengembalikan 0 untuk mencegah error.
Semua tuts hitam di oktaf ke-3, ke-4 dan ke-5 ditampilkan dengan benar, termasuk posisi dan labelnya.
Finally
Setiap tuts putih dan hitam memiliki nada-nada dari oktaf ke-3, ke-4, dan ke-5.
1. Nada Tuts Putih dan Hitam: Setiap tuts putih dan hitam memiliki label nada dari oktaf ke-3, ke-4, dan ke-5.
2. Pola Tuts Hitam: Mengikuti pola [0, 1, 2, 3, 5, 6, 7, 8, 9] di setiap oktaf.
3. Oktav: Ditambahkan ke setiap label tuts (misalnya, E3, F3, ..., E4, F4).
4. Fungsi Peta Frekuensi: Disesuaikan agar semua nada di tiga oktaf dapat dimainkan.
Kode ini memastikan bahwa setiap tuts mencakup nada dari oktaf ke-3 hingga ke-5 dengan posisi tuts hitam yang benar. Silakan jalankan untuk memverifikasi hasilnya.
Comments
Post a Comment