Saya sudah mulai menulis sebuah program dalam C ++ 11 yang akan menganalisis akord, skala, dan harmoni. Masalah terbesar yang saya miliki dalam fase desain saya, adalah bahwa not 'C' adalah not, jenis akor (Cmaj, Cmin, C7, dll), dan jenis kunci (kunci Cmajor, Cminor). Masalah yang sama muncul dengan interval (minor ke-3, ke-3 utama).
Saya menggunakan kelas dasar, Token, itu adalah kelas dasar untuk semua 'simbol' dalam program. jadi misalnya:
class Token {
public:
typedef shared_ptr<Token> pointer_type;
Token() {}
virtual ~Token() {}
};
class Command : public Token {
public:
Command() {}
pointer_type execute();
}
class Note : public Token;
class Triad : public Token; class MajorTriad : public Triad; // CMajorTriad, etc
class Key : public Token; class MinorKey : public Key; // Natural Minor, Harmonic minor,etc
class Scale : public Token;
Seperti yang Anda lihat, untuk membuat semua kelas turunan (CMajorTriad, C, CMajorScale, CMajorKey, dll) akan dengan cepat menjadi sangat rumit termasuk semua catatan lainnya, serta enharmonics. multiple inheritance tidak akan berfungsi, yaitu:
class C : public Note, Triad, Key, Scale
kelas C, tidak bisa semuanya pada saat yang bersamaan. Itu kontekstual, juga polymorphing dengan ini tidak akan bekerja (bagaimana menentukan metode super untuk melakukan? Memanggil setiap konstruktor kelas super tidak boleh terjadi di sini)
Apakah ada ide atau saran desain yang ditawarkan orang? Saya belum dapat menemukan apa pun di Google dalam hal memodelkan harmoni tonal dari perspektif OO. Ada terlalu banyak hubungan di antara semua konsep di sini.
sumber
Jawaban:
Saya pikir pendekatan terbaik adalah mereproduksi hubungan nyata antara entitas-entitas ini.
Misalnya, Anda dapat memiliki:
sebuah
Note
objek, yang sifat yangnama (C, D, E, F, G, A, B)
tidak disengaja (alami, datar, tajam)
frekuensi atau pengidentifikasi nada unik lainnya
sebuah
Chord
objek, yang sifat yangberbagai
Note
objeknama
kebetulan
kualitas (utama, kecil, berkurang, ditambah, ditangguhkan)
tambahan (7, 7+, 6, 9, 9+, 4)
sebuah
Scale
objek, yang sifat yangberbagai
Note
objeknama
jenis (utama, minor alami, minor melodi, minor harmonik)
mode (ion, dorian, frigia, lydia, mixolidian, aeolian, lokal)
Kemudian, jika input Anda adalah teks, Anda dapat membuat catatan dengan string termasuk nama catatan, tidak disengaja dan (jika Anda membutuhkannya) oktaf.
Sebagai contoh (kodesemu, saya tidak tahu C ++):
Kemudian, di
Note
kelas Anda dapat mengurai string dan mengatur properti.A
Chord
dapat dibangun dengan catatannya:... atau dengan string termasuk nama, kualitas, dan catatan tambahan:
Saya tidak tahu persis apa yang akan dilakukan aplikasi Anda, jadi ini hanya ide.
Semoga sukses dengan proyek menarik Anda!
sumber
Beberapa saran umum.
Jika ada banyak ketidakpastian yang diharapkan dalam desain kelas (seperti dalam situasi Anda), saya akan merekomendasikan bereksperimen dengan berbagai desain kelas yang bersaing.
Menggunakan C ++ pada tahap ini mungkin tidak seproduktif bahasa lain. (Masalah ini jelas dalam fragmen kode Anda harus berurusan dengan
typedef
danvirtual
destruktor.) Bahkan jika tujuan proyek adalah untuk menghasilkan kode C ++, mungkin produktif untuk melakukan desain kelas awal dalam bahasa lain. (Misalnya Java, meskipun ada banyak pilihan.)Jangan memilih C ++ hanya karena multiple inheritance. Multiple inheritance memiliki kegunaannya tetapi itu bukan cara yang tepat untuk memodelkan masalah ini (teori musik).
Berikan perhatian khusus pada disambiguasi. Meskipun ambiguitas berlimpah dalam deskripsi bahasa Inggris (tekstual), ambiguitas ini harus diselesaikan ketika merancang kelas OOP.
Kita berbicara tentang G dan G tajam sebagai catatan. Kita berbicara tentang G mayor dan G minor sebagai skala. Dengan demikian,
Note
danScale
bukan konsep yang dapat dipertukarkan. Tidak mungkin ada objek yang dapat secara bersamaan menjadi instance dari aNote
dan aScale
.Halaman ini berisi beberapa diagram yang menggambarkan hubungan: http://www.howmusicworks.org/600/ChordScale-Relations/Chord-and-Scale-Relations
Sebagai contoh lain, "Triad yang dimulai dengan G pada skala C mayor " tidak memiliki arti yang sama dengan "Triad yang dimulai dengan C pada skala G mayor ".
Pada tahap awal ini,
Token
kelas (superclass of everything) tidak beralasan, karena mencegah disambiguasi. Ini bisa diperkenalkan nanti jika diperlukan (didukung oleh fragmen kode yang menunjukkan bagaimana ini bisa berguna.)Untuk memulainya, mulailah dengan
Note
kelas yang merupakan pusat diagram kelas, kemudian secara bertahap tambahkan hubungan (potongan data yang perlu dikaitkan dengan tupelNote
s) ke diagram hubungan kelas.Sebuah C catatan adalah turunan dari
Note
kelas. Sebuah C catatan akan kembali properti yang berkaitan dengan catatan ini, seperti triad terkait, dan posisi relatif (Interval
) sehubungan denganScale
yang dimulai dengan C catatan.Hubungan antara instance dari kelas yang sama (misalnya, antara catatan C dan catatan E ) harus dimodelkan sebagai properti, bukan warisan.
Selain itu, banyak hubungan antar kelas dalam contoh Anda juga lebih tepat dimodelkan sebagai properti. Contoh:
(contoh kode tertunda karena saya perlu mempelajari kembali teori musik ...)
sumber
Pada dasarnya, not musik adalah frekuensi dan interval musik adalah rasio frekuensi.
Segala sesuatu yang lain dapat dibangun di atas itu.
Chord adalah daftar interval. Skala adalah nada dasar dan sistem tuning. Sistem penyetelan juga merupakan daftar interval.
Bagaimana Anda menamainya hanyalah artefak budaya.
Artikel teori Musik Wikipedia adalah titik awal yang bagus.
sumber
Saya menemukan diskusi ini menarik.
Apakah catatan dimasukkan melalui midi (atau beberapa jenis alat penangkap nada) atau dimasukkan dengan mengetik huruf dan simbol?
Dalam hal interval dari C ke D-sharp / E-flat:
Meskipun D-sharp dan E-flat adalah nada yang sama (sekitar 311Hz jika A = 440Hz), interval dari C -> D-sharp ditulis sebagai augmented 2nd, sedangkan interval dari C -> E-flat ditulis sebagai minor 3. Cukup mudah jika Anda tahu bagaimana catatan itu ditulis. Tidak mungkin untuk menentukan apakah Anda hanya memiliki dua nada untuk melanjutkan.
Dalam hal ini, saya percaya Anda juga akan membutuhkan cara untuk menambah / mengurangi nada bersama dengan metode .Sharpen () dan .Flatten () yang disebutkan, seperti .SemiToneUp (), .FullToneDown (), dll. Jadi Anda dapat menemukan catatan subesquent dalam skala tanpa "mewarnai" mereka sebagai benda tajam / flat.
Saya harus setuju dengan @Rotem bahwa "C" bukan kelas di dalam dan dari dirinya sendiri, melainkan sebuah instance dari kelas Note.
Jika Anda mendefinisikan properti untuk catatan, termasuk semua interval sebagai semi-nada, maka terlepas dari nilai catatan awal ("C", "F", "G #") Anda akan dapat mengatakan bahwa urutan catatan tiga yang memiliki root, mayor 3 (M3), lalu minor 3 (m3) akan menjadi triad utama. Demikian pula, m3 + M3 adalah triad kecil, m3 + m3 berkurang, M3 + M3 ditambah. Selain itu, ini akan memberi Anda cara untuk merangkum menemukan 11, berkurang 13, dll. Tanpa secara eksplisit mengkodekan mereka untuk semua 12 catatan dasar, dan oktaf mereka naik dan turun.
Setelah selesai, Anda masih memiliki beberapa masalah untuk diselesaikan.
Ambil triad C, E, G. Sebagai seorang musisi, saya melihat ini dengan jelas sebagai akord Cmaj. Namun, pengembang dalam diri saya dapat menafsirkan tambahan ini sebagai E minor Augment 5 (Root E + m3 + a5) atau Gsus4 ke-6 no 5 (RootG + 4 + 6).
Jadi, untuk menjawab pertanyaan Anda tentang melakukan analisis, saya pikir cara terbaik untuk menentukan modalitas (maj, minor, dll) adalah dengan mengambil semua catatan yang dimasukkan, mengaturnya dalam nilai semi naik, dan mengujinya terhadap bentuk akor yang dikenal . Kemudian, gunakan setiap catatan yang dimasukkan sebagai catatan root, dan lakukan serangkaian evaluasi yang sama.
Anda bisa memberi bobot pada bentuk akor sehingga lebih umum (mayor, minor) lebih diutamakan daripada bentuk akor yang diperbesar, ditangguhkan, elektra, dll., Tetapi analisis yang akurat akan membutuhkan penyajian semua bentuk akor yang cocok sebagai solusi yang memungkinkan.
Lagi-lagi artikel wikipedia yang direferensikan melakukan pekerjaan yang baik untuk mendaftarkan kelas pitch, jadi seharusnya sederhana (walaupun membosankan) untuk membuat kode model chord, mengambil catatan yang dimasukkan, menugaskan mereka ke kelas pitch / interval, dan kemudian membandingkan terhadap bentuk yang diketahui untuk pertandingan.
Ini sangat menyenangkan. Terima kasih!
sumber
Kedengarannya seperti kasing untuk templat. Anda tampaknya memiliki
template <?> class Major : public Chord;
apaMajor<C>
adanyaChord
, seperti apa adanyaMajor<B>
. Demikian pula, Anda juga memilikiNote<?>
templat dengan instanceNote<C>
danNote<D>
.Satu-satunya hal yang saya tinggalkan adalah
?
bagian. Tampaknya Anda memilikienum {A,B,C,D,E,F,G}
tetapi saya tidak tahu bagaimana Anda akan menyebut enum itu.sumber
Terima kasih atas semua sarannya, entah bagaimana saya berhasil melewatkan tanggapan ekstra. Sejauh ini kelas saya telah dirancang seperti ini:
Untuk menyelesaikan masalah perhitungan interval dan akor, saya memutuskan untuk menggunakan buffer sirkular, yang memungkinkan saya untuk melintasi buffer dari titik mana pun, maju, hingga saya menemukan catatan berikutnya yang cocok.
Untuk menemukan interval yang ditafsirkan - lewati buffer note nyata, berhentilah ketika hurufnya cocok (hanya hurufnya, bukan not atau posisi sebenarnya) jadi c - g # = 5
Untuk menemukan jarak nyata- lintasi buffer lain dari 12 bilangan bulat, berhentilah ketika posisi nada teratas sama dengan nilai buffer pada indeks, sekali lagi ini hanya bergerak maju. Tapi offset bisa di mana saja (mis. Buffer.at (-10))
sekarang saya tahu interval yang ditafsirkan, dan jarak fisik antara keduanya. jadi nama interval sudah setengah lengkap.
sekarang saya dapat menafsirkan interval, yaitu. jika intervalnya 5, dan jaraknya 8, maka itu adalah augmented 5th.
Sejauh ini note dan interval berfungsi seperti yang diharapkan, sekarang saya hanya perlu menangani pengenal akor.
Terima kasih sekali lagi, saya akan membaca kembali beberapa tanggapan ini dan memasukkan beberapa ide di sini.
sumber