Floppy & HDD Music
- Войдите на сайт для отправки комментариев
Вс, 29/05/2016 - 15:17
Собственно, см. видео https://youtu.be/oq2bXXktJQs
Подробности чуть позже.
Собственно, см. видео https://youtu.be/oq2bXXktJQs
Подробности чуть позже.
Не понял, звук что-ли сами дисководы издают? Или звук от звуковой карты а на дисководах просто "цветомузыка" сделана?
Судя по звукам, шумит механика. По крайней мере, местами. Вот еще.
Нет, Женя, вместо динамиков используются именно дисководы. А вместо звуковой платы - Ардуино, настроенный на частоту прерываний 40 кГц.
Видео промежуточных этапов:
https://www.youtube.com/watch?v=VqNxzM-S5dk&lc=z12kslihsyapfhpxs04cjp5hv...
https://www.youtube.com/watch?v=k1sQ6k0-MXY
Проект представляет, по сути, музыкальную шкатулку, собранную на базе Ardiono Pro Mini, трех Floppy дисководов и двух накопителей на жестких дисках.
Все это располагается в корпусе теперь уже наверное винтажного ПК цвета слоновой кости. Блок питания - оттуда же: стандартный компьютерный.
Каждый floppy может воспроизводить один голос, а HDD - 2. Итого 7 голосов.
Не обошлось и без некоторой "фейковатости": один НЖМД расположен в корпусе от старого пишущего CDD. Индикаторы, задающие режимы работы, заменены индикаторами включения соответствующих голосов. Второй НЖМД находится в стандартном Mobile Rack'е, но индикаторам присвоемы другие функции - как у первомго НЖМД.
FDD взяты без переделки, но используются только три сигнала: "выбор устройства", "направление" и "шаг". Собственно, шаговый двигатель с головкой и излучают звук. В процесе экспериментов выяснилось, что наиболее грмкий и отчетливый звук (понятное дело, разработчики, наоборот, стремятся сделать свои устройства как можно тише) достигается, если разрешить дисководу перемещаться только в пределах двух (а не 40-80) дорожек. Правда, появляется призвук октавой ниже, но для данного проекта это, возможно, даже плюс.
А вот HDD подверглись серьезной переделке:
- удалена плата контроллера,
- удалены блины и мотор,
- удалены некоторые конструктивные элементы, препятствующие свободному перемещению коромысла.
В И-нете аналогичные проекты попадаются не так уж редко, но, почему-то, везде рекомендуется подпаивать подводящие провода непосредственно к контактам катушки коромысла, хотя коромысло уже соединено с неподвижной колодкой гибким шлейфом, который заодно служит упругим элементом, позиционирующим головку примерно в середину диапазона свободного хода. Я подсоединялся к неподвижному концу шлейфа, в одном случае даже удалось использовать съемный контакт, выпаянный из платы контроллера.
Звук в HDD излучает коромысло, катушка которого имеет сопротивление порядка 7-9 Ом, т.е. такое же, как у стандартного динамика. Поэтому и сигнал на нее подавался со стандартного УМЗЧ, собранного на TDA2004, схема которого была слегка доработана, исходя из особенностей применения.
В качестве радиатора УМЗЧ использовался массивный корпус HDD. Естественно, с использованием теплопроводящей пасты. Усилитель питался от 12В, а индикаторы - от 5В, т.к. активному режиму соответствует низкий уровень (это стандартно для цифровой электроники и для FDD в частности, поэтому было решено не отказываться от этого стандарта и при переделке HDD). Такой подход требует подачи на устройство напряжения 5В, чего можно было бы избежать, если бы активный сигнал был высоким. Но т.к. питание все равно осуществлялось через стандартный molex, было решено оставить, как есть.
Для управления переделанным HDD используется 4 контакта: "звук 1-го канала", "выбор 1-го канала", "звук 2-го канала" и "выбор 2-го канала". "Звук" подается на входы усилителя, а катушка коромысла подключена по "мостовой" схеме. "Выбор" используется исключительно для зажигания светодиодов.
Исходники:
Основная программа:
001
#include <TimerOne.h>
002
#include "Arhat_digOut.c"
003
#include "voice_0.c"
004
#include "voice_1.c"
005
#include "voice_2.c"
006
#include "voice_3.c"
007
#include "voice_4.c"
008
#include "voice_5.c"
009
#include "voice_6.c"
010
011
// change interrupt period to 25us (40kHz) insteadо 40us (25kHz)
012
// minimum frequence for 3.5" floppy is 440-520 Hz
013
014
// channel 0, vely low notes: 5.25 floppy - up to ()
015
#define pin_sound_0 8 //2 // sound pin, for floppy - step
016
#define pin_dir_0 9 //3 // step direction pin, for floppy only
017
#define pin_active_0 10 //4 // for LED & activate floppy drive
018
019
// channel 1, low notes: 3.5 floppy - up to C1-F1 (261-347 Hz)
020
#define pin_sound_1 5 // sound pin, for floppy - step
021
#define pin_dir_1 6 // step direction pin, for floppy only
022
#define pin_active_1 7 // for LED & activate floppy drive
023
024
// channel 2, low notes: 3.5 floppy: up to C1-F1 (261-347 Hz)
025
#define pin_sound_2 2 //8 // sound pin, for floppy - step
026
#define pin_dir_2 3 //9 // step direction pin, for floppy only
027
#define pin_active_2 4 //10 // for LED & activate floppy drive
028
029
// channel 3, high notes: 1-st HDD 1-st channel - not limited
030
#define pin_sound_3 11 // sound pin, for HDD - sound amplifier
031
#define pin_active_3 12 // for LED only
032
033
// channel 4, high notes: 1-st HDD 2-nd channel - not limited
034
#define pin_sound_4 13 // sound pin, for HDD - sound amplifier
035
#define pin_active_4 14 // for LED only
036
037
// channel 5, high notes: 2-nd HDD 1-st channel - not limited
038
#define pin_sound_5 15 // sound pin, for HDD - sound amplifier
039
#define pin_active_5 16 // for LED only
040
041
// channel 6, high notes: 2-nd HDD 2-nd channel - not limited
042
#define pin_sound_6 17 // sound pin, for HDD - sound amplifier
043
#define pin_active_6 18 // for LED only
044
045
#define pin_button_0 19 // for button input
046
047
#define RESOLUTION 25 //Microsecond resolution for notes (interrupt frequency 40 kHz)
048
#define FREQUENCE 1000/RESOLUTION // interrupt frequence in kHz
049
050
byte
MAX_POSITION_0 = 2;
//74; // max head position: double number of track without 2, for 5.25 - 40 tracks
051
byte
MAX_POSITION_1 = 2;
//154; // max head position: double number of track without 2, for 3.5 - 80 tracks
052
byte
MAX_POSITION_2 = 2;
//154; // max head position: double number of track without 2, for 3.5 - 80 tracks
053
054
byte
currentPosition[] = {0, 0, 0};
// head position (track number)
055
056
char
currentStateAdd_0 = 1;
// addition for currentPosition -1 or +1 (track)
057
char
currentStateAdd_1 = 1;
058
char
currentStateAdd_2 = 1;
059
060
byte
currentStateStep[] = {0,0,0,0,0,0,0};
// positive or negative half period
061
unsigned
int
currentPeriodA[] = {0,0,0,0,0,0,0};
// positive half period 0 = off.
062
unsigned
int
currentPeriodB[] = {0,0,0,0,0,0,0};
// negative half period 0 = off.
063
064
unsigned
int
currentTick_0 = 1;
// sound half-perion counter (from currentPeriod*[] to 0)
065
unsigned
int
currentTick_1 = 1;
066
unsigned
int
currentTick_2 = 1;
067
unsigned
int
currentTick_3 = 1;
068
unsigned
int
currentTick_4 = 1;
069
unsigned
int
currentTick_5 = 1;
070
unsigned
int
currentTick_6 = 1;
071
072
unsigned
long
startTime;
073
074
void
setup
(){
075
Serial
.begin(115200);
076
077
for
(
byte
i = 2; i <= 18; i++)
078
pinMode(i, OUTPUT);
// 0-1 - Serial, 2-10 - floppy control, 11-18 - HDD control, 19(,A6,A7) - buttons
079
pinMode(A5, INPUT_PULLUP);
080
081
resetAll();
082
083
Timer1.initialize(RESOLUTION);
// Set up a timer at the defined resolution
084
Timer1.attachInterrupt(tick);
// Attach the tick function
085
086
resetAll();
087
delay(2000);
088
startTime = millis();
089
}
090
091
void
loop
(){
092
unsigned
long
currTime = millis() - startTime;
093
static
unsigned
int
index[7] = {0,0,0,0,0,0,0};
// array index of the note of each channels
094
static
byte
melodyOver[7] = {0,0,0,0,0,0,0};
095
if
(!melodyOver[0]) {
096
if
(pgm_read_word(&bach_ch_0[index[0] << 1]) <= currTime/tick_0) {
// even values in arrays are start time
097
unsigned
int
pp = pgm_read_word(&bach_ch_0[(index[0] << 1) + 1]);
// and odd are note period. 0 - pause, 65535 - end
098
if
(pp == 65535){
099
pp = 0;
100
melodyOver[0] = 1;
101
}
102
currentPeriodA[0] = pp/2;
103
currentPeriodB[0] = pp - pp/2;
104
currentTick_0 = currentPeriodA[0];
105
if
(pp != 0) {
106
digitalWrite(pin_active_0, LOW);
107
}
else
{
108
digitalWrite(pin_active_0, HIGH);
109
digitalWrite(pin_sound_0, LOW);
110
}
111
index[0]++;
112
}
113
}
114
if
(!melodyOver[1]) {
115
if
(pgm_read_word(&bach_ch_1[index[1] << 1]) <= currTime/tick_1) {
116
unsigned
int
pp = pgm_read_word(&bach_ch_1[(index[1] << 1) + 1]);
117
if
(pp == 65535){
118
pp = 0;
119
melodyOver[1] = 1;
120
}
121
currentPeriodA[1] = pp/2;
122
currentPeriodB[1] = pp - pp/2;
123
currentTick_1 = currentPeriodA[1];
124
if
(pp != 0) {
125
digitalWrite(pin_active_1, LOW);
126
}
else
{
127
digitalWrite(pin_active_1, HIGH);
128
digitalWrite(pin_sound_1, LOW);
129
}
130
index[1]++;
131
}
132
}
133
if
(!melodyOver[2]) {
134
if
(pgm_read_word(&bach_ch_2[index[2] << 1]) <= currTime/tick_2) {
135
unsigned
int
pp = pgm_read_word(&bach_ch_2[(index[2] << 1) + 1]);
136
if
(pp == 65535){
137
pp = 0;
138
melodyOver[2] = 1;
139
}
140
currentPeriodA[2] = pp/2;
141
currentPeriodB[2] = pp - pp/2;
142
currentTick_2 = currentPeriodA[2];
143
if
(pp != 0) {
144
digitalWrite(pin_active_2, LOW);
145
}
else
{
146
digitalWrite(pin_active_2, HIGH);
147
digitalWrite(pin_sound_2, LOW);
148
}
149
index[2]++;
150
}
151
}
152
153
if
(!melodyOver[3]) {
154
if
(pgm_read_word(&bach_ch_3[index[3] << 1]) <= currTime/tick_3) {
155
unsigned
int
pp = pgm_read_word(&bach_ch_3[(index[3] << 1) + 1]);
156
if
(pp == 65535){
157
pp = 0;
158
melodyOver[3] = 1;
159
}
160
currentPeriodA[3] = pp/2;
161
currentPeriodB[3] = pp - pp/2;
162
currentTick_3 = currentPeriodA[3];
163
if
(pp != 0) {
164
digitalWrite(pin_active_3, LOW);
165
}
else
{
166
digitalWrite(pin_active_3, HIGH);
167
digitalWrite(pin_sound_3, LOW);
168
}
169
index[3]++;
170
}
171
}
172
if
(!melodyOver[4]) {
173
if
(pgm_read_word(&bach_ch_4[index[4] << 1]) <= currTime/tick_4) {
174
unsigned
int
pp = pgm_read_word(&bach_ch_4[(index[4] << 1) + 1]);
175
if
(pp == 65535){
176
pp = 0;
177
melodyOver[4] = 1;
178
}
179
currentPeriodA[4] = pp/2;
180
currentPeriodB[4] = pp - pp/2;
181
currentTick_4 = currentPeriodA[4];
182
if
(pp != 0) {
183
digitalWrite(pin_active_4, LOW);
184
}
else
{
185
digitalWrite(pin_active_4, HIGH);
186
digitalWrite(pin_sound_4, LOW);
187
}
188
index[4]++;
189
}
190
}
191
if
(!melodyOver[5]) {
192
if
(pgm_read_word(&bach_ch_5[index[5] << 1]) <= currTime/tick_5) {
193
unsigned
int
pp = pgm_read_word(&bach_ch_5[(index[5] << 1) + 1]);
194
if
(pp == 65535){
195
pp = 0;
196
melodyOver[5] = 1;
197
}
198
currentPeriodA[5] = pp/2;
199
currentPeriodB[5] = pp - pp/2;
200
currentTick_5 = currentPeriodA[5];
201
if
(pp != 0) {
202
digitalWrite(pin_active_5, LOW);
203
}
else
{
204
digitalWrite(pin_active_5, HIGH);
205
digitalWrite(pin_sound_5, LOW);
206
}
207
index[5]++;
208
}
209
}
210
if
(!melodyOver[6]) {
211
if
(pgm_read_word(&bach_ch_6[index[6] << 1]) <= currTime/tick_6) {
212
unsigned
int
pp = pgm_read_word(&bach_ch_6[(index[6] << 1) + 1]);
213
if
(pp == 65535){
214
pp = 0;
215
melodyOver[6] = 1;
216
}
217
currentPeriodA[6] = pp/2;
218
currentPeriodB[6] = pp - pp/2;
219
currentTick_6 = currentPeriodA[6];
220
if
(pp != 0) {
221
digitalWrite(pin_active_6, LOW);
222
}
else
{
223
digitalWrite(pin_active_6, HIGH);
224
digitalWrite(pin_sound_6, LOW);
225
}
226
index[6]++;
227
}
228
}
229
}
230
231
/* Called by the timer inturrupt at the specified resolution. */
232
void
tick()
// elapsed time ~12us (~50%)
233
{
234
// If there is a period set for control pin 2, count the number of
235
// ticks that pass, and toggle the pin if the current period is reached.
236
/////////////////////////////////////////////////////////////////////////////
237
if
(currentPeriodA[0]){
// if the note is on
238
currentTick_0--;
// decrease tick counter
239
if
(currentTick_0 <= 0){
// half-period has been finished
240
if
(currentPosition[0] >= MAX_POSITION_0) {
// Switch head directions if end has been reached
241
currentStateAdd_0 = -1;
242
pinOutHigh(pin_dir_0);
243
}
else
if
(currentPosition[0] <= 0) {
244
currentStateAdd_0 = 1;
245
pinOutLow(pin_dir_0);
246
}
247
currentPosition[0] += currentStateAdd_0;
//Update currentPosition
248
if
(currentStateStep[0]) {
249
pinOutHigh(pin_sound_0);
//Pulse the control pin
250
currentStateStep[0] = LOW;
251
currentTick_0 = currentPeriodA[0];
252
}
else
{
253
pinOutLow(pin_sound_0);
//Pulse the control pin
254
currentStateStep[0] = HIGH;
255
currentTick_0 = currentPeriodB[0];
256
}
257
}
258
}
259
260
if
(currentPeriodA[1]){
261
currentTick_1--;
262
if
(currentTick_1 <= 0){
263
if
(currentPosition[1] >= MAX_POSITION_1) {
264
currentStateAdd_1 = -1;
265
pinOutHigh(pin_dir_1);
266
}
else
if
(currentPosition[1] <= 0) {
267
currentStateAdd_1 = 1;
268
pinOutLow(pin_dir_1);
269
}
270
currentPosition[1] += currentStateAdd_1;
//Update currentPosition
271
if
(currentStateStep[1]) {
272
pinOutHigh(pin_sound_1);
273
currentStateStep[1] = LOW;
274
currentTick_1 = currentPeriodA[1];
275
}
else
{
276
pinOutLow(pin_sound_1);
//Pulse the control pin
277
currentStateStep[1] = HIGH;
278
currentTick_1 = currentPeriodB[1];
279
}
280
}
281
}
282
283
if
(currentPeriodA[2]){
284
currentTick_2--;
285
if
(currentTick_2 <= 0){
286
if
(currentPosition[2] >= MAX_POSITION_2) {
287
currentStateAdd_2 = -1;
288
pinOutHigh(pin_dir_2);
289
}
else
if
(currentPosition[2] <= 0) {
290
currentStateAdd_2 = 1;
291
pinOutLow(pin_dir_2);
292
}
293
currentPosition[2] += currentStateAdd_2;
//Update currentPosition
294
if
(currentStateStep[2]) {
295
pinOutHigh(pin_sound_2);
//Pulse the control pin
296
currentStateStep[2] = LOW;
297
currentTick_2 = currentPeriodA[2];
298
}
else
{
299
pinOutLow(pin_sound_2);
//Pulse the control pin
300
currentStateStep[2] = HIGH;
301
currentTick_2 = currentPeriodB[2];
302
}
303
}
304
}
305
306
if
(currentPeriodA[3]){
307
currentTick_3--;
308
if
(currentTick_3 <= 0){
309
if
(currentStateStep[3]) {
310
pinOutHigh(pin_sound_3);
//Pulse the control pin
311
currentStateStep[3] = LOW;
312
currentTick_3 = currentPeriodA[3];
313
}
else
{
314
pinOutLow(pin_sound_3);
//Pulse the control pin
315
currentStateStep[3] = HIGH;
316
currentTick_3 = currentPeriodB[3];
317
}
318
}
319
}
320
321
if
(currentPeriodA[4]){
322
currentTick_4--;
323
if
(currentTick_4 <= 0){
324
if
(currentStateStep[4]) {
325
pinOutHigh(pin_sound_4);
//Pulse the control pin
326
currentStateStep[4] = LOW;
327
currentTick_4 = currentPeriodA[4];
328
}
else
{
329
pinOutLow(pin_sound_4);
//Pulse the control pin
330
currentStateStep[4] = HIGH;
331
currentTick_4 = currentPeriodB[4];
332
}
333
}
334
}
335
336
if
(currentPeriodA[5]){
337
currentTick_5--;
338
if
(currentTick_5 <= 0){
339
if
(currentStateStep[5]) {
340
pinOutHigh(pin_sound_5);
//Pulse the control pin
341
currentStateStep[5] = LOW;
342
currentTick_5 = currentPeriodA[5];
343
}
else
{
344
pinOutLow(pin_sound_5);
//Pulse the control pin
345
currentStateStep[5] = HIGH;
346
currentTick_5 = currentPeriodB[5];
347
}
348
}
349
}
350
351
if
(currentPeriodA[6]){
352
currentTick_6--;
353
if
(currentTick_6 <= 0){
354
if
(currentStateStep[6]) {
355
pinOutHigh(pin_sound_6);
//Pulse the control pin
356
currentStateStep[6] = LOW;
357
currentTick_6 = currentPeriodA[6];
358
}
else
{
359
pinOutLow(pin_sound_6);
//Pulse the control pin
360
currentStateStep[6] = HIGH;
361
currentTick_6 = currentPeriodB[6];
362
}
363
}
364
}
365
}
366
367
//Resets all the pins
368
void
resetAll(){
369
370
pinOutHigh(pin_dir_0);
// reverse direction
371
pinOutHigh(pin_dir_1);
372
pinOutHigh(pin_dir_2);
373
pinOutLow(pin_active_0);
// drive enable
374
pinOutLow(pin_active_1);
375
pinOutLow(pin_active_2);
376
377
// New all-at-once reset
378
for
(
byte
s=0;s<80;s++){
// For max drive's position
379
pinOutHigh(pin_sound_0);
380
pinOutHigh(pin_sound_1);
381
pinOutHigh(pin_sound_2);
382
delay(3);
383
pinOutLow(pin_sound_0);
384
pinOutLow(pin_sound_1);
385
pinOutLow(pin_sound_2);
386
delay(3);
387
}
388
389
currentPosition[0] = 0;
// We're reset.
390
currentPosition[1] = 0;
// We're reset.
391
currentPosition[2] = 0;
// We're reset.
392
393
pinOutLow(pin_dir_0);
// forward direction
394
pinOutLow(pin_dir_1);
395
pinOutLow(pin_dir_2);
396
pinOutHigh(pin_active_0);
// drive disable
397
pinOutHigh(pin_active_1);
398
pinOutHigh(pin_active_2);
399
pinOutHigh(pin_active_3);
400
pinOutHigh(pin_active_4);
401
pinOutHigh(pin_active_5);
402
pinOutHigh(pin_active_6);
403
404
// 2 steps forward
405
for
(
byte
s=0;s<2;s++){
// For max drive's position
406
pinOutHigh(pin_sound_0);
407
pinOutHigh(pin_sound_1);
408
pinOutHigh(pin_sound_2);
409
delay(3);
410
pinOutLow(pin_sound_0);
411
pinOutLow(pin_sound_1);
412
pinOutLow(pin_sound_2);
413
delay(3);
414
}
415
}
Файл с описанием команд быстрого вывода в порт (спасибо Arhat)
001
#include <avr/pgmspace.h>
002
003
#define OREG0 PORTD
004
#define OREG1 PORTD
005
#define OREG2 PORTD
006
#define OREG3 PORTD
007
#define OREG4 PORTD
008
#define OREG5 PORTD
009
#define OREG6 PORTD
010
#define OREG7 PORTD
011
#define OREG8 PORTB
012
#define OREG9 PORTB
013
#define OREG10 PORTB
014
#define OREG11 PORTB
015
#define OREG12 PORTB
016
#define OREG13 PORTB
017
#define OREG14 PORTC // PORTB
018
#define OREG15 PORTC // PORTB
019
#define OREG16 PORTC
020
#define OREG17 PORTC
021
#define OREG18 PORTC
022
#define OREG19 PORTC
023
//#define OREG20 PORTC
024
//#define OREG21 PORTC
025
//#define OREG22 PORTC
026
027
#define SET_MASK_0 (uint8_t)1
028
#define SET_MASK_1 (uint8_t)2
029
#define SET_MASK_2 (uint8_t)4
030
#define SET_MASK_3 (uint8_t)8
031
#define SET_MASK_4 (uint8_t)16
032
#define SET_MASK_5 (uint8_t)32
033
#define SET_MASK_6 (uint8_t)64
034
#define SET_MASK_7 (uint8_t)128
035
036
#define CLR_MASK_0 (uint8_t)254
037
#define CLR_MASK_1 (uint8_t)253
038
#define CLR_MASK_2 (uint8_t)251
039
#define CLR_MASK_3 (uint8_t)247
040
#define CLR_MASK_4 (uint8_t)239
041
#define CLR_MASK_5 (uint8_t)223
042
#define CLR_MASK_6 (uint8_t)191
043
#define CLR_MASK_7 (uint8_t)127
044
045
#define BSET0 SET_MASK_0
046
#define BCLR0 CLR_MASK_0
047
048
#define BSET1 SET_MASK_1
049
#define BCLR1 CLR_MASK_1
050
051
#define BSET2 SET_MASK_2
052
#define BCLR2 CLR_MASK_2
053
054
#define BSET3 SET_MASK_3
055
#define BCLR3 CLR_MASK_3
056
057
#define BSET4 SET_MASK_4
058
#define BCLR4 CLR_MASK_4
059
060
#define BSET5 SET_MASK_5
061
#define BCLR5 CLR_MASK_5
062
063
#define BSET6 SET_MASK_6
064
#define BCLR6 CLR_MASK_6
065
066
#define BSET7 SET_MASK_7
067
#define BCLR7 CLR_MASK_7
068
069
#define BSET8 SET_MASK_0
070
#define BCLR8 CLR_MASK_0
071
072
#define BSET9 SET_MASK_1
073
#define BCLR9 CLR_MASK_1
074
075
#define BSET10 SET_MASK_2
076
#define BCLR10 CLR_MASK_2
077
078
#define BSET11 SET_MASK_3
079
#define BCLR11 CLR_MASK_3
080
081
#define BSET12 SET_MASK_4
082
#define BCLR12 CLR_MASK_4
083
084
#define BSET13 SET_MASK_5
085
#define BCLR13 CLR_MASK_5
086
087
#define BSET14 SET_MASK_0 // SET_MASK_6
088
#define BCLR14 CLR_MASK_0 // CLR_MASK_6
089
090
#define BSET15 SET_MASK_1 // SET_MASK_7
091
#define BCLR15 CLR_MASK_1 // CLR_MASK_7
092
093
#define BSET16 SET_MASK_2 // SET_MASK_6
094
#define BCLR16 CLR_MASK_2 // CLR_MASK_6
095
096
#define BSET17 SET_MASK_3 // SET_MASK_0
097
#define BCLR17 CLR_MASK_3 // CLR_MASK_0
098
099
#define BSET18 SET_MASK_4 // SET_MASK_1
100
#define BCLR18 CLR_MASK_4 // CLR_MASK_1
101
102
#define BSET19 SET_MASK_5 // SET_MASK_2
103
#define BCLR19 CLR_MASK_5 // CLR_MASK_2
104
105
//#define BSET20 SET_MASK_3
106
//#define BCLR20 CLR_MASK_3
107
108
//#define BSET21 SET_MASK_4
109
//#define BCLR21 CLR_MASK_4
110
111
//#define BSET22 SET_MASK_5
112
//#define BCLR22 CLR_MASK_5
113
114
#define pinOutReg(p) (OREG##p)
115
#define pinSetMask(p) (BSET##p)
116
#define pinClearMask(p) (BCLR##p)
117
#define pinOutHigh(p) (pinOutReg(p) |= pinSetMask(p)) // out 1 (HIGH) to pin. Установка на выводе лог.1:
118
#define pinOutLow(p) (pinOutReg(p) &= pinClearMask(p)) // out 0 (LOW) to pin. Установка на выводе лог.0:
119
#define pinOut(p,v) ((v)? pinOutHigh(p) : pinOutLow(p)) // @see digitalWrite().
Файлы с данными
01
#include <avr/pgmspace.h>
02
03
#define tick_0 2
04
#define NumNotes_0 2
05
06
// Sound Sample Rate: 40000 Hz
07
08
const
unsigned
int
bach_ch_0[] PROGMEM = {
09
8640, 545,
10
14385, 65535
11
};
01
#include <avr/pgmspace.h>
02
03
#define tick_1 2
04
#define NumNotes_1 54
05
06
// Sound Sample Rate: 40000 Hz
07
08
const
unsigned
int
bach_ch_1[] PROGMEM = {
09
10, 91,
10
40, 0,
11
55, 102,
12
85, 0,
13
105, 91,
14
960, 0,
15
970, 102,
16
1000, 0,
17
1025, 115,
18
1055, 0,
19
1070, 121,
20
1100, 0,
21
1105, 136,
22
1140, 0,
23
1160, 144,
24
1675, 0,
25
1715, 136,
26
2015, 0,
27
2895, 182,
28
2920, 0,
29
2935, 204,
30
2970, 0,
31
2985, 182,
32
3780, 0,
33
3860, 243,
34
4015, 0,
35
4040, 229,
36
4200, 0,
37
4220, 289,
38
4375, 0,
39
4390, 272,
40
4760, 0,
41
5775, 364,
42
5810, 0,
43
5820, 408,
44
5855, 0,
45
5870, 364,
46
6715, 0,
47
6740, 408,
48
6765, 0,
49
6785, 458,
50
6805, 0,
51
6820, 485,
52
6850, 0,
53
6870, 545,
54
6895, 0,
55
6910, 577,
56
7440, 0,
57
7465, 545,
58
7775, 0,
59
9135, 289,
60
12465, 0,
61
12480, 272,
62
14385, 65535
63
};
01
#include <avr/pgmspace.h>
02
03
#define tick_2 2
04
#define NumNotes_2 52
05
06
// Sound Sample Rate: 40000 Hz
07
08
const
unsigned
int
bach_ch_2[] PROGMEM = {
09
10, 45,
10
50, 0,
11
65, 51,
12
95, 0,
13
105, 45,
14
955, 0,
15
980, 51,
16
1010, 0,
17
1020, 57,
18
1055, 0,
19
1070, 61,
20
1100, 0,
21
1105, 68,
22
1145, 0,
23
1150, 72,
24
1680, 0,
25
1705, 68,
26
2015, 0,
27
2900, 91,
28
2930, 0,
29
2935, 102,
30
2975, 0,
31
2980, 91,
32
3785, 0,
33
3860, 121,
34
4020, 0,
35
4035, 115,
36
4205, 0,
37
4210, 144,
38
4385, 0,
39
4400, 136,
40
4755, 0,
41
5775, 182,
42
5810, 0,
43
5815, 204,
44
5865, 0,
45
5870, 182,
46
6715, 0,
47
6740, 204,
48
6780, 0,
49
6775, 229,
50
6820, 0,
51
6830, 243,
52
6860, 0,
53
6875, 272,
54
6905, 0,
55
6910, 289,
56
7440, 0,
57
7465, 272,
58
7770, 0,
59
9600, 243,
60
12465, 65535
61
};
01
#include <avr/pgmspace.h>
02
03
#define tick_3 2
04
#define NumNotes_3 7
05
06
// Sound Sample Rate: 40000 Hz
07
08
const
unsigned
int
bach_ch_3[] PROGMEM = {
09
10095, 204,
10
12405, 0,
11
12480, 204,
12
12945, 0,
13
12975, 243,
14
13440, 216,
15
14385, 65535
16
};
01
#include <avr/pgmspace.h>
02
03
#define tick_4 2
04
#define NumNotes_4 4
05
06
// Sound Sample Rate: 40000 Hz
07
08
const
unsigned
int
bach_ch_4[] PROGMEM = {
09
10560, 172,
10
12465, 0,
11
12480, 182,
12
14385, 65535
13
};
1
01
#include <avr/pgmspace.h>
02
03
#define tick_5 2
04
#define NumNotes_5 54
05
06
// Sound Sample Rate: 40000 Hz
07
08
const
unsigned
int
bach_ch_5[] PROGMEM = {
09
0, 91,
10
30, 0,
11
45, 102,
12
75, 0,
13
90, 91,
14
945, 0,
15
960, 102,
16
990, 0,
17
1005, 115,
18
1035, 0,
19
1050, 121,
20
1080, 0,
21
1095, 136,
22
1125, 0,
23
1140, 144,
24
1665, 0,
25
1695, 136,
26
1995, 0,
27
2880, 182,
28
2910, 0,
29
2925, 204,
30
2955, 0,
31
2970, 182,
32
3765, 0,
33
3840, 243,
34
4005, 0,
35
4020, 229,
36
4185, 0,
37
4200, 289,
38
4365, 0,
39
4380, 272,
40
4740, 0,
41
5760, 364,
42
5790, 0,
43
5805, 408,
44
5835, 0,
45
5850, 364,
46
6705, 0,
47
6720, 408,
48
6750, 0,
49
6765, 458,
50
6795, 0,
51
6810, 485,
52
6840, 0,
53
6855, 545,
54
6885, 0,
55
6900, 577,
56
7425, 0,
57
7455, 545,
58
7755, 0,
59
11055, 144,
60
12465, 0,
61
12480, 136,
62
14385, 65535
63
};
01
#include <avr/pgmspace.h>
02
03
#define tick_6 2
04
#define NumNotes_6 52
05
06
// Sound Sample Rate: 40000 Hz
07
08
const
unsigned
int
bach_ch_6[] PROGMEM = {
09
0, 45,
10
30, 0,
11
45, 51,
12
85, 0,
13
90, 45,
14
945, 0,
15
960, 51,
16
1000, 0,
17
1005, 57,
18
1045, 0,
19
1050, 61,
20
1090, 0,
21
1095, 68,
22
1135, 0,
23
1140, 72,
24
1665, 0,
25
1695, 68,
26
1995, 0,
27
2880, 91,
28
2910, 0,
29
2925, 102,
30
2965, 0,
31
2970, 91,
32
3765, 0,
33
3840, 121,
34
4005, 0,
35
4020, 115,
36
4185, 0,
37
4200, 144,
38
4365, 0,
39
4380, 136,
40
4740, 0,
41
5760, 182,
42
5790, 0,
43
5805, 204,
44
5845, 0,
45
5850, 182,
46
6705, 0,
47
6720, 204,
48
6760, 0,
49
6765, 229,
50
6805, 0,
51
6810, 243,
52
6850, 0,
53
6855, 272,
54
6895, 0,
55
6900, 289,
56
7425, 0,
57
7455, 272,
58
7755, 0,
59
11520, 121,
60
12480, 65535
61
};
Ахренеть!
Снимаю шляпу!
крутотень! а Ду Хаст можно так сделать?
В принципе можно сделать что угодно - 7 голосов достаточно для вменяемой аранжировки любого произведения. В частности, в том фрагменте, что на видео, у Баха звучит максимум 9 нот, так что кое-где пришлось подсократить октаву.
С другой стороны, звук принципиально без динамики. Так что впечатление от результата может быть делеким от желаемого. Наиболее адекватно звучат органные партии.
понял, спасибо за ответ.
примерно так и подумал (про органные партии).