آهنگ های زنگ Atmega8. آژیرهای صوتی ساده در MK AVR. با استفاده از ماژول صدا

در این مقاله اصول سنتز موسیقی در AVR توضیح داده شده است. نرم افزار ارائه شده به شما اجازه می دهد تا هر فایل midi را به آن تبدیل کنید منبعدر C برای میکروکنترلرهای AVR برای اضافه کردن پخش قطعات موسیقی به پیشرفت های آماده. نمونه ای از استفاده از نرم افزار در جعبه موسیقی در نظر گرفته شده است.

ابتدا، یک ویدیوی کوتاه از نحوه کار همه چیز:

آنچه که نرم افزار اجازه می دهد

نرم افزار PC به شما امکان می دهد یک منبع C برای CodeVision AVR دریافت کنید که فایل midi انتخاب شده را پخش می کند:

1. common\hxMidiPlayer.h, common\hxMidiPlayer.c را به پروژه خود وصل کنید. الگوهای ATMega8Example\melody.h، ATMega8Example\melody.c، ATMega8Example\hxMidiPlayer_config.h را کپی کرده و وصل کنید.
2. MidiToC.exe را راه اندازی کنید
3. فایل Midi را بارگذاری کنید.
4. پخش کننده را تنظیم کنید: نرخ نمونه برداری، تعداد کانال ها، شکل موج و غیره. نرم افزار ملودی را به همان روشی که AVR پخش می کند پخش می کند.
5. روی «Create player config» کلیک کنید و منبع را در hxMidiPlayer_config.h قرار دهید.
6. روی «ایجاد کد ملودی» کلیک کنید و منبع را در melody.c قرار دهید
7. در پروژه خود، ما متد Player_Output() را برای خروجی صدا از طریق PWM یا DAC خارجی پیاده سازی می کنیم.
8. تایمر را روی Sampling rate تنظیم کنید و Player_TimerFunc() را از وقفه فراخوانی کنید.
9. Player_StartMelody (&s_melody، 0) را فراخوانی کنید.

ملودی از وقفه تایمر پخش می شود. این بدان معنی است که در حین پخش، میکروکنترلر می تواند کارهای مفیدی نیز انجام دهد.

چگونه کار می کند

در ادامه مقاله سعی خواهم کرد به طور خلاصه نحوه اجرای همه اینها را توضیح دهم. متأسفانه، خیلی کوتاه نخواهد بود - مطالب زیادی وجود دارد. اگر علاقه ای ندارید، می توانید مستقیماً به بخش «توضیحات نرم افزار» و «Player API» بروید.

موسیقی چیست

موسیقی دنباله ای از صداها با فرکانس ها و مدت زمان های مختلف است. فرکانس هارمونیک اصلی یک صدا باید با فرکانس یک نت خاص مطابقت داشته باشد. اگر فرکانس ارتعاش صداها با فرکانس نت ها متفاوت باشد، به نظر می رسد که نوازنده "خارج از لحن" است.

جدول. توجه داشته باشید فرکانس، هرتز.

همه نت‌ها به اکتاو تقسیم می‌شوند، 7 نت در هر + 5 نیم‌تون (کلیدهای سیاه روی پیانو). فرکانس نت ها در اکتاوهای مجاور دقیقاً 2 برابر متفاوت است.

ساده ترین پخش کننده موسیقی شامل یک جدول با ترتیب نت ها (نت + مدت زمان) یک ملودی و یک جدول با فرکانس های نت است. برای سنتز صدا از یکی از کانال های تایمر استفاده می شود که یک پیچ و خم را تشکیل می دهد:

متأسفانه چنین نوازنده ابتدایی شکل موج ثابتی دارد (موج مربع) که شباهت زیادی به آلات موسیقی واقعی ندارد و می تواند در هر نوبت فقط یک نت بنوازد.

یک ملودی واقعی حداقل شامل دو قسمت (انفرادی + باس) است و وقتی با پیانو نواخته می‌شود، نت قبلی همچنان به صدا در می‌آید که نت بعدی شروع می‌شود. درک این موضوع با به خاطر سپردن ساختار پیانو آسان است - هر نت مربوط به یک سیم جداگانه است. می‌توانیم با کشیدن دست‌هایمان روی کلیدها، همزمان چندین سیم را به صدا در بیاوریم.

برخی از میکروکنترلرها دارای چندین کانال تایمر هستند که می توان از آنها برای پخش همزمان چندین نت استفاده کرد. اما معمولاً این کانال ها منبع ارزشمندی هستند و استفاده از همه آنها توصیه نمی شود. البته مگر اینکه فقط یک جعبه موسیقی بسازیم.
در مجموع، برای به دست آوردن چند صدایی و صداهای مختلف آلات موسیقی، باید از سنتز صدا استفاده کنید.

سنتز صدا در AVR

hxMidiPlayer از سنتز صدا استفاده می کند و می تواند چند صدایی را با شکل موج های مختلف پخش کند. پخش کننده دامنه سیگنال خروجی را در کنترل کننده وقفه تایمر با فرکانس 8-22 کیلوهرتز محاسبه می کند (میزان قدرت پردازنده کافی است؛ همچنین به شکل موج و تعداد کانال ها بستگی دارد).

اصل سنتز صدا را می توان با استفاده از مثال سنتز سینوسی توضیح داد.

بیایید جدولی به اندازه 64 بگیریم که در هر سلول آن مقادیر دامنه سینوسی در شاخص نقاط * 2 * PI / 64 (یک نقطه) نوشته شده است:

فلش ثابت uint8_t s_sineTable[ 64 ] = ( 0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8D, 0x8F, 0x90, 0x91, 0x9,0x9,0x9, 0x9, 0x9, 0x93 5، 0x95، 0x95، 0x94، 0x93، 0x93، 0x91، 0x90، 0x8F، 0x8D، 0x8C، 0x8A، 0x88، 0x86، 0x84، 0x82، 0x80، 0x7E، 0x7C، 0x7، 0x7x0، 0x7x0 0x70، 0x6F، 0x6D، 0x6D، 0x6C، 0x6B، 0x6B، 0x6B، 0x6B، 0x6B، 0x6C، 0x6D، 0x6D، 0x6F، 0x70، 0x71، 0x73، 0x74، 0x76، 0x7E, 0x78، 0x7C،

128 (0x80) برابر با صفر، 255 (0xff) به بزرگترین نقطه مثبت، 0 به بزرگترین نقطه منفی است.

حال فرض کنید مقادیر را از جدول به یک DAC خارجی در یک وقفه تایمر با فرکانس 1000 هرتز خروجی می دهیم:

استاتیک uint8_t s_index = 0; // خروجی Timer1 مقایسه یک وقفه روتین سرویس وقفه void timer1_compa_isr(void) (SetDac(s_sineTable[ s_index]); if (s_index == 63) (s_index = 0; ) other (s_index++; ))

در نتیجه چه چیزی بدست خواهیم آورد؟ نوسانات سینوسی با فرکانس 1000/64 هرتز خواهیم داشت.

حالا بیایید شاخص را در وقفه نه 1، بلکه دو افزایش دهیم.
بدیهی است که فرکانس نوسان خروجی در حال حاضر 1000/64 * 2 هرتز خواهد بود.

به طور کلی، برای به دست آوردن فرکانس F، باید شاخص جدول را به میزان زیر افزایش دهید:
افزودن = F / 1000 * 64

این عدد می تواند کسری باشد اما برای به دست آوردن سرعت بالا از حساب نقطه ثابت استفاده می شود.

تعداد ورودی های جدول و فرکانس تایمر بر کیفیت صدای سنتز شده تأثیر می گذارد. در مورد ما، 64 ورودی در جدول در هر دوره کافی است و فرکانس تایمر 12 کیلوهرتز است. حداقل فرکانس قابل قبول تایمر 8 کیلوهرتز است، ایده آل آن 44 کیلوهرتز است.

بدیهی است که با فرکانس تایمر 12 کیلوهرتز، ما می توانیم حداکثر 6 کیلوهرتز امواج مربعی تولید کنیم، زیرا باید حداقل دو سوئیچ در هر دوره ایجاد کنیم. با این حال، اگر وضعیت خروجی در هر تیک تایمر به درستی محاسبه شود، فرکانس‌های بالاتر همچنان قابل تشخیص خواهند بود.

می توانید مقادیر دوره نوسانات غیر سینوسی را در جدول وارد کنید و صدای متفاوتی دریافت کنید.

تضعیفی

اگر یک ساز موسیقی مبتنی بر سیم (مثلا پیانو) باشد، پس از فشار دادن یک کلید، صدا به آرامی محو می شود. برای به دست آوردن صدای سینتی سایزر طبیعی تر، باید دامنه ارتعاشات را پس از شروع نت به آرامی کاهش دهید (ارتعاشات را در یک فرم کاهش دهنده - "پاکت").

پخش کننده حاوی یک جدول فروپاشی است که از آن برای کاهش دامنه سینوس (یا شکل موج دیگر) از لحظه شروع نت استفاده می کند.
"سینه" "پیچیده شده" در چنین پوسته ای شبیه صدای یک جعبه موسیقی مکانیکی است.

سنتز پیچ و خم

شکل خاص موج پرپیچ و خم اجازه می دهد تا سنتز به طور قابل توجهی ساده شود. در این مورد از جداول استفاده نمی شود. کافی است محاسبه کنید که خروجی در یک فرکانس معین در تیک تایمر فعلی چه حالتی (1 یا 0) باید داشته باشد. این کار با استفاده از محاسبات اعداد صحیح انجام می شود و بسیار سریع کار می کند، که محبوبیت استفاده از پیچ و خم برای پخش ملودی ها در جعبه های 8 بیتی را توضیح می دهد.

مثال: اعلام شمارنده:

استاتیک uint16_t s_counter = 0;

که در هر وقفه تایمر 0x8000 افزایش می دهیم و مهم ترین بیت شمارنده به پورت خروجی می شود:

// خروجی Timer1 مقایسه وقفه روتین سرویس وقفه void timer1_compa_isr(void) ( PORTA.0 = (s_counter >> 15) & 1; s_counter += 0x8000; )

از آنجایی که 0x8000 + 0x8000 = 0x10000، متغیر s_counter سرریز می شود، بیت هفدهم کنار گذاشته می شود و 0x0000 روی متغیر نوشته می شود.
بنابراین، با فرکانس تایمر 8 کیلوهرتز، خروجی یک موج مربعی 4 کیلوهرتز خواهد بود.
اگر شمارنده را 0x4000 افزایش دهید، یک موج مربعی 2 کیلوهرتز دریافت می کنید.

به طور کلی، می توانید فرکانس F را با اضافه کردن:
افزودن = F / 8000 * 0x10000

به عنوان مثال، برای به دست آوردن یک موج مربعی با فرکانس 1234 هرتز، باید 0x277C را اضافه کنید. فرکانس واقعی کمی با فرکانس داده شده متفاوت خواهد بود، زیرا عبارت را به یک عدد کامل گرد می کنیم. این در یک سینت سایزر قابل قبول است.

سنتز صداهای سازهای واقعی

می توانید صدای نت را قبل از پیانو دیجیتالی کنید (با استفاده از ADC برای ذخیره مقادیر دامنه صدا در حافظه در فواصل زمانی معین):
و سپس صدا را پخش کنید (با استفاده از DAC برای خروجی مقادیر ضبط شده در فواصل منظم).

به طور کلی، برای سنتز درام، باید صداهای درام را ضبط کرده و در لحظه مناسب پخش کنید. در کنسول های 8 بیتی به جای صدای درام از "نویز سفید" استفاده می شود. مقادیر دامنه برای "نویز سفید" با استفاده از یک ژنراتور به دست می آید اعداد تصادفی. هزینه های حافظه حداقل است.
hxMidiPlayer از "نویز سفید" برای سنتز درام استفاده می کند.

اختلاط کانال

دامنه صدا در یک تیک تایمر معین برای هر کانال به طور جداگانه محاسبه می شود. برای به دست آوردن مقدار دامنه نهایی، باید مقادیر همه کانال ها را اضافه کنید. به درستی، لازم است مجموع را تنظیم کنید، زیرا بلندی درک شده از وابستگی لگاریتمی تبعیت می کند، اما در چنین سینت سایزر ساده باید به جمع ساده بسنده کنید. بنابراین حداکثر دامنه هر کانال 255/N است.

خروجی صدا از AVR

پس از انجام تمام محاسبات لازم، بازیکن سطح سیگنالی را دریافت می کند که باید به آنالوگ تبدیل شود. برای این منظور می توانید از DAC یا PWM خارجی استفاده کنید.
در اینجا لازم به ذکر است که در هر دو مورد توصیه می شود سیگنال دریافتی را فیلتر کنید - برای حذف نویز با فرکانس بالا که به دلیل فرکانس کم سنتز و گرد کردن ایجاد می شود.

خروجی به DAC موازی خارجی

از آنجایی که استفاده از تراشه های DAC دقیق منطقی نیست، چنین پروژه هایی معمولاً با ماتریس R2R کار می کنند:

با این طرح، ما به سادگی دامنه محاسبه شده را به پورت خروجی می دهیم:

PORTB = نمونه;

ایرادات:
1) خروجی ماتریس R2R نیز می باشد سیگنال ضعیف، استفاده از تقویت کننده آنالوگ اجباری است.
2) استفاده از حداقل 5 پین (و ترجیحاً 8) ضروری است.
این روش تنها زمانی قابل توجیه است که کانال PWM رایگان وجود نداشته باشد.

(برای ذخیره پین ​​ها، می توانید از یک ADC خارجی با رابط SPI استفاده کنید).

PWM

اگر یک کانال PWM رایگان وجود دارد، ساده ترین راه استفاده از این روش است.

مقداردهی اولیه PWM (ATMega8):

// مقداردهی اولیه تایمر/ شمارنده 2 // منبع ساعت: ساعت سیستم // مقدار ساعت: 20000.000 کیلوهرتز // حالت: سریع PWM top=0xFF // خروجی OC2: غیر معکوس PWM ASSR=0x00; TCCR2=0x69; TCNT2=0x00; OCR2=0x00; و خروجی نمونه: void Player_Output (uint8_t نمونه) ( OC2 = نمونه. )

روش معمول برای استفاده از PWM شامل صاف کردن سیگنال خروجی با استفاده از فیلتر RC است:

متأسفانه، پس از فیلتر کردن، سیگنال بیش از حد ضعیف می شود، بنابراین باید یک تقویت کننده آنالوگ برای اتصال بلندگو بسازید.

برای ساده کردن مدار، بهتر است تا زمانی که خود بلندگو "دیجیتال" باقی بماند. از آنجایی که یک بلندگوی ارزان هنوز نمی تواند فرکانس های بالای 30 کیلوهرتز را بازتولید کند، نیازی به فیلتر کردن آنها نیست. خود دیفیوزر فرکانس های PWM بالا را "فیلتر" می کند.

اگر نیاز به دریافت جریان بیشتر دارید، می توانید از تقویت کننده ترانزیستوری استفاده کنید. R1 برای تامین جریان مورد نیاز به بلندگو انتخاب می شود.

به این ترتیب می توانید بلندگوهای کوچک را از اسباب بازی ها وصل کنید:

برای بلندگوهای بزرگتر، بهتر است درایو را با استفاده از 2 ترانزیستور مونتاژ کنید و یک فیلتر LC برای حذف نویز نصب کنید:

خازن C1 برای محدود کردن جریان عبوری از بلندگو در زمانی که PWM کار نمی کند عمل می کند. همچنین به دلیل گنجاندن یک خازن سری، سیگنالی متقارن حدود صفر به بلندگو می رسد. بنابراین، مخروط بلندگو نسبت به موقعیت "آرام" مرکزی حرکت می کند که تأثیر مثبتی بر کیفیت صدا دارد.
در این حالت ترانزیستورها در حالت سوئیچینگ کار می کنند، بنابراین نیازی به جبران افست پایه نیست.

PWM، اتصال دو پین

عیب دو مدار اول این است که بلندگو در یک جهت جریان دارد. اگر جهت جریان را تغییر دهیم، بدون تجاوز از توان مجاز، می توان حجم را 2 برابر افزایش داد. برای انجام این کار، بلندگو به دو پایه میکروکنترلر متصل می شود - غیر معکوس و معکوس، به عنوان مثال OC1A و /OC1A. اگر خروجی غیر معکوس وجود ندارد، می توانید از کانال دوم در حالت معکوس (OC1B) استفاده کنید:

// مقدار دهی اولیه تایمر/ شمارنده 1 // منبع ساعت: ساعت سیستم // مقدار ساعت: 24500000 کیلوهرتز // حالت: سریع PWM top=0x00FF // خروجی OC1A: Non-Inv. // خروجی OC1B: معکوس // حذف نویز: خاموش // ضبط ورودی در لبه سقوط // تایمر 1 وقفه سرریز: خاموش // وقفه ضبط ورودی: خاموش // مقایسه وقفه مسابقه: خاموش // مقایسه B وقفه مطابقت: خاموش TCCR1A =0xB1; TCCR1B=0x09; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; void Player_Output (uint8_t نمونه) ( OCR1A = نمونه؛ OCR1B = نمونه؛ )

PWM، دو پایه، تقویت کننده کلاس D

نقطه ضعف مدارهای پیشنهادی مصرف جریان در هنگام سکوت است.
"سکوت" برای ما مربوط به سطح سیگنال 128 است، یعنی PWM با 50٪ پر شدن - جریان همیشه از بلندگو عبور می کند!

با کمی تغییر نرم افزار، می توانید یک تقویت کننده نرم افزاری و سخت افزاری نسبتاً قدرتمند کلاس D دریافت کنید:

Void Player_Output(uint8_t نمونه) (اگر (نمونه >= 128) (TCCR2=0x21; //نرمال، در مقایسه با مطابقت پاک شد TCCR2=0x21 | 0x80; //CLEAR OC2 PORTC.0 = 0; TCCR2=0x69; //non - معکوس کردن PWM OCR2 = (نمونه-128) * 2 ) else // if (نمونه< 128) { TCCR2=0x31; //normal, set on compare match TCCR2=0x31 | 0x80; //SET OC2 PORTC.0 = 1; TCCR2=0x79; //inverting PWM OCR2 = (128-sample) *2; } }

در این حالت، یک جفت ترانزیستور به خروجی PWM و دومی به یک خروجی دیجیتال معمولی متصل می شود.

همانطور که از کد می بینید، سیگنال بالای 128 را به عنوان جریانی که در یک جهت هدایت می شود، و سیگنال زیر 128 را به عنوان جریانی که در جهت دیگر هدایت می شود، در نظر می گیریم. در 128 هر دو پایه بلندگو به یک پایه منبع تغذیه متصل هستند و جریانی وجود ندارد. هنگام انحراف از سطح 128، پر شدن PWM افزایش می یابد و جریانی با قطبیت مربوطه از طریق بلندگو عبور می کند.

نکته مهم در اجرا، سوئیچ اجباری خروجی PWM به حالت دلخواه در لحظه سوئیچینگ پین دوم (دیجیتال معمولی) (PORTC.0) است. نوشتن در رجیستر OCR2 برای حذف اشکالات PWM بافر می شود. ما باید فوراً خروجی PWM را تغییر دهیم، بدون اینکه منتظر پایان دوره باشیم.

مدار دوم IMHO از نظر سادگی، صرفه جویی در انرژی و توان خروجی بهترین گزینه است.

خروجی صدا با شکل موج SquareWave

هنگام سنتز یک پیچ و خم، از الگوریتم های ساده شده استفاده می شود.

هر کانال (از جمله درام) 0 یا 1 را خروجی می دهد. بنابراین، یک صفحه گردان 3 کاناله مقادیری در محدوده 0..3 خروجی می دهد. بنابراین، هنگام استفاده از PWM، روند خروجی به نظر می رسد:

Void Player_Output (uint8_t نمونه) ( OCR2 = نمونه * (255 / HXMIDIPLAYER_CHANNELS_COUNT)؛ )

اگر از PWM استفاده نمی کنید، برای خروجی یک ملودی 3 کانال، دو خروجی دیجیتال معمولی و یک ماتریس R2R 2 بیتی کافی است.

فرمت MIDI

اگر به کد ملودی حاصل نگاه کنید، به راحتی می توانید ببینید که آرایه از اعداد تکرار شونده از محدوده کوچکی استفاده می کند. این قابل درک است: ملودی از تعداد محدودی نت در 1-2 اکتاو استفاده می کند، سرعت ملودی ثابت است - تاخیرهای مساوی، تعداد کانال ها در محدوده 0..15 است.
همه اینها به این معنی است که آرایه حاصل را می توان با اعمال نوعی الگوریتم فشرده سازی به میزان قابل توجهی کاهش داد.
الگوریتم‌هایی مانند ZIP فشرده‌سازی خوبی را ارائه می‌کنند، اما برای کار کردن به حافظه زیادی نیز نیاز دارند (ZIP فرهنگ لغت - 64 کیلوبایت). ما می توانیم از یک روش فشرده سازی بسیار ساده استفاده کنیم که عملاً نیازی به حافظه ندارد که ماهیت آن به شرح زیر است.

در یک بایت، همه اعداد به طور مساوی در محدوده 0...255 توزیع می شوند و هر عدد با 8 بیت نمایش داده می شود. در مورد ما، برخی از اعداد بسیار رایج تر از دیگران هستند. اگر اعداد متداول را با بیت های کمتر رمزگذاری کنید، و اعداد کمتری را با بیت های بیشتر رمزگذاری کنید، می توانید افزایش حافظه داشته باشید.

ما یک روش رمزگذاری ثابت را انتخاب می‌کنیم: ترکیب بیت‌های 000001 و 010 (طول - 3 بیت) 3 عددی را که اغلب رخ می‌دهند را نشان می‌دهند. ترکیب بیت 0110، 0111 (طول - 4 بیت) - 2 عدد رایج بعدی و غیره:

//000..010 - 0..2 //011 x 3..4 //100 xx 5..8 //101 xxx 9..16 //110 xxx 17..24 //111 فوری

ترکیبی که با 111 شروع می شود (طول - 11 بیت) همه اعداد دیگر را رمزگذاری می کند.
روش رمزگذاری بیت ممکن است متفاوت باشد. من چندین روش را امتحان کردم و این یکی را به عنوان بهترین نتایج در چنین داده هایی انتخاب کردم.

روش فشرده سازی به صورت زیر است:
1. تعداد کل عدد X در جریان را برای X = محاسبه کنید.
2. مرتب سازی بر اساس کاهش فرکانس ظاهر در جریان.
3. 25 عدد اول را در نظر بگیرید. آنها در بیت های کمتری کدگذاری می شوند.
4. جریان ورودی را رمزگذاری کنید.

خروجی آرایه ای از 25 عدد رایج و جریان بیت است.
این فشرده سازی به شما این امکان را می دهد که با حداقل هزینه حافظه و عملکرد به 50٪ فشرده سازی دست یابید. متأسفانه، این کد پخش کننده را افزایش می دهد، بنابراین فشرده سازی برای ملودی های کوتاه توصیه نمی شود.

ذخیره سازی فرکانس های یادداشت

ذخیره کردن فرکانس تمام نت ها در یک جدول از حافظه بسیار گران است. در واقع، فرمولی برای تعیین فرکانس یک نت با عدد میدی آن وجود دارد:

F = 2^((N - 69)/12) * 440، هرتز

اما محاسبه توان کسری بسیار دشوار است. در عوض، پخش کننده 12 فرکانس نت را در اکتاو بالایی ذخیره می کند. فرکانس نت ها در اکتاوهای پایین تر با کاهش فرکانس 2^Y بار بیشتر تعیین می شود، جایی که Y تعداد اکتاوهای پایین تر است.

توسعه بیشتر فشرده سازی

این ملودی اغلب شامل قطعات تکراری ("همخوانی"، "آیات") است. با یافتن قطعات تکراری و ارائه ملودی به صورت قطعه، می توانید ملودی را تا 50 درصد دیگر کاهش دهید، تقریباً هیچ وقت صرف نمی کنید. رمو بهره وری. من چنین الگوریتمی را اجرا نکردم تا پروژه را پیچیده نکنم.

توضیحات نرم افزار

پنجره اصلی برنامه مبدل:

دکمه Load Midi به شما امکان می دهد یک فایل midi را بارگذاری کنید. برنامه بلافاصله شروع به پخش فایل با پارامترهای انتخاب شده فعلی می کند و صدایی را که در سخت افزار خواهد بود شبیه سازی می کند.

پنجره اطلاعات (4) نمایش می دهد:
- طول - طول قطعه ملودی انتخاب شده در میلی ثانیه؛
– حداکثر کانال های سینت سایزر فعال – حداکثر تعداد کانال های سینت سایزر فعال به طور همزمان.
- حداکثر کانال های درام فعال - حداکثر تعداد کانال های سینت سایزر فعال همزمان که "درام" را تولید می کنند.
– حداکثر نت‌های استریو فعال – حداکثر تعداد کانال‌هایی که همان نت را تولید می‌کنند (به زیر مراجعه کنید).
– اندازه تخمینی، بایت – اندازه ملودی بر حسب بایت. در حالت "نمونه سفارشی"، اندازه به صورت A+B نمایش داده می شود، جایی که A اندازه ملودی، B اندازه نمونه است. اندازه کد پخش کننده در اینجا مشخص نشده است.

پنجره پیشرفت موقعیت فعلی پخش را نشان می دهد.
می توانید روی نوار پیشرفت کلیک کنید تا پخش از نقطه مشخص شده شروع شود.
جعبه های ورودی در سمت چپ و راست به شما امکان می دهند ابتدا و انتهای قطعه ملودی را بر حسب ms مشخص کنید.

برچسب "عدم کافی کانال برای پخش ملودی" به رنگ قرمز نشان می دهد که کانال های سینت سایزر کافی برای پخش ملودی با تنظیمات فعلی وجود ندارد. اگر پخش کننده یک کانال رایگان پیدا نکرد، قدیمی ترین یادداشت را خاموش می کند. در بسیاری از موارد این کار به خوبی انجام خواهد شد. افزایش تعداد کانال ها تنها زمانی منطقی است که ملودی در گوش نادرست به نظر برسد.

تنظیمات را می توان به تنظیمات پخش کننده و تنظیمات پردازش فایل midi تقسیم کرد. اگر پیکربندی پخش کننده و کد ملودی با تنظیمات پخش کننده یکسان ایجاد شده باشند، پخش کننده می تواند کد ملودی حاصل را پخش کند. علاوه بر این، پخش کننده می تواند ملودی را پخش کند که کد آن برای پخش کننده ای با تعداد کانال های کمتر (اما نه بیشتر) ایجاد شده است.

تنظیمات سخت افزار پلیر عبارتند از:

– نرخ نمونه برداری – فرکانس سنتز. حداکثر فرکانس همجوشی به صورت تجربی تعیین می شود. بر اساس Atmega 16 مگاهرتز، می توانید برای پخش کننده با 6 کانال از 12000 هرتز شروع کنید و آن را به دلخواه افزایش دهید تا زمانی که اعوجاج ملودی در پخش کننده سخت افزاری قابل توجه باشد. حداکثر فرکانس به تعداد کانال ها، شکل موج و پیچیدگی خود ملودی بستگی دارد.

– شکل موج – شکل موج:
- موج مربعی - پیچ و خم؛
– سینوس – سینوس؛
– سینوس + پاکت – سینوس با تضعیف.
- شکل موج * + پاکت - گزینه های مختلف برای امواج غیر سینوسی با و بدون تضعیف.
– نمونه سفارشی – از نمونه ابزار استفاده کنید.

دکمه "بارگیری نمونه" به شما امکان می دهد نمونه ای را از یک فایل WAV بارگیری کنید. فایل WAV باید به صورت PCM 8 بیتی مونو، 4173 هرتز، C-5 باشد. نکته: می توانید فرکانس را افزایش دهید و نت را کم کنید، اما Pitch را در تنظیمات پخش کننده تغییر دهید. هیچ بررسی فرمتی وجود ندارد - اگر فرمت متفاوت باشد، صدا به درستی پخش نمی شود.
Pitch – به شما امکان می دهد زیر و بم صدا را تغییر دهید. به عنوان مثال، برای پخش 1 اکتاو بالاتر، باید Pitch +12 را تنظیم کنید.

از فشرده سازی استفاده کنید - از فشرده سازی ملودی استفاده کنید.
فعال کردن سینت سایزر درام - سینت سایزر درام را فعال کنید.

کانال های پخش کننده: تعداد کانال های سینتی سایزر (حداکثر تعداد نت هایی که به طور همزمان به صدا در می آیند).

تنظیمات پردازش فایل Midi عبارتند از:

به طور معمول، چنین تنظیم دقیق مورد نیاز نیست. این تنظیمات را می توان به عنوان پیش فرض باقی گذاشت.

Player API

اجرای پخش کننده در فایل های Common\hxMidiPlayer.c و Common\hxMidiPlayer.h قرار دارد. این فایل ها باید در پروژه گنجانده شوند. همچنین باید یک فایل hxMidiPlayer_config.h ایجاد کنید که باید تنظیمات را در آن قرار دهید.
پخش کننده به زبان C بدون درج اسمبلی نوشته شده است که باعث می شود به راحتی آن را به میکروکنترلرهای دیگر منتقل کنید.

Extern void Player_StartMelody(const flash TMelody* _pMelody, uint16_t _delay);

شروع به نواختن ملودی کنید. _delay تاخیر اولیه را قبل از پخش تنظیم می کند، 255 واحد = 1 ثانیه.

Void Player_Stop();

نواختن ملودی را متوقف کنید.

Extern bool Player_IsPlaying();

اگر پخش ملودی تمام شده باشد، false را برمی‌گرداند.

فضای خالی خارجی Player_WaitFinish();

منتظر بمانید تا پخش ملودی تمام شود.

Extern void Player_TimerFunc();

این تابع باید در یک وقفه تایمر با نرخ نمونه برداری مشخص شده در پیکربندی فراخوانی شود. وقتی پخش ملودی تمام شد، نیازی به برقراری تماس ندارید.

Extern void Player_Output (uint8_t sample);

باید توسط کاربر پیاده سازی شود. هنگامی که نمونه بعدی باید خروجی شود توسط بازیکن فراخوانی می شود.

Extern void Player_Started();

باید توسط کاربر پیاده سازی شود. زمانی که پخش کننده شروع به نواختن ملودی می کند تماس گرفته می شود. می توان از آن برای پیکربندی وقفه های تایمر استفاده کرد.

فضای خالی خارجی Player_Finished();

باید توسط کاربر پیاده سازی شود. زمانی که پخش کننده نواختن ملودی را تمام کرد، تماس گرفته می شود. می توان از آن برای غیرفعال کردن وقفه های تایمر یا شروع پخش آهنگ دیگری استفاده کرد.

//#define NOTES_TO_EEPROM //#define SINETABLE_TO_EEPROM //#define ENVELOPE_TO_EEPROM

این خطوط باید در فایل hxMidiPlayer_config.h حذف شوند، اگر جدول یادداشت، جدول سینوسی و جدول تضعیف باید در eeprom قرار گیرند.

پروژه های نمونه

ATMega644Example – پروژه برای خروجی ATMega644، 25 مگاهرتز، PWM در PB3.

نیازهای حافظه

جدول. اندازه پخش کننده و ملودی ها در فلش.

*هنگام افزودن یک بازیکن به یک پروژه غیر خالی موجود، اندازه کد کوچکتر خواهد بود

** کانال های کافی برای پخش ملودی معمولی وجود ندارد

ملودی 1: bach_minuet_in_g.mid، 35 ثانیه
ملودی 2: yiruma-river_flows_in_you.mid، 165 ثانیه
ملودی 3: فرانتس شوبرت – سرناد. اواسط، 217 ثانیه

همانطور که از جدول می بینید، در یک پیکربندی حداقلی می توانید یک ملودی نسبتا طولانی را حتی در ATTiny2313 فشار دهید. فشرده سازی می تواند ملودی را بیش از دو برابر کاهش دهد، اما اندازه کد پخش کننده تا 600 بایت افزایش می یابد.

جداول نت های سینوسی و فروپاشی را می توان در EEPROM قرار داد و به ترتیب در حدود 16، 50 و 100 بایت فلاش صرفه جویی کرد.

هنگام استفاده از یک نمونه از یک فایل wav، باید اندازه نمونه را بر حسب بایت به اندازه کد پخش کننده اضافه کنید.

مثال استفاده

به عنوان مثالی از استفاده از یک پخش کننده، اجازه دهید روند ایجاد یک جعبه موسیقی را در نظر بگیریم.

یک جعبه ام دی اف آماده می گیریم:

به عنوان یک میکروکنترلر، ما ATTiny85 را در بسته SO-8 به عنوان ارزانترین با مقدار کافی حافظه انتخاب می کنیم. ما آن را تا 27 مگاهرتز اورکلاک می کنیم تا فرکانس سنتز 18 کیلوهرتز را با 4 کانال Sine+Envelope بدست آوریم.

تقویت کننده از کلاس D با 4 ترانزیستور برای صرفه جویی در باتری خواهد بود.

ترانزیستورها در حالت سوئیچینگ کار می کنند و می توانند از هر نوع باشند. سلف L1 و خازن C6 بر اساس سلیقه انتخاب می شوند تا صدا بدون نویز فرکانس بالا به دست آید. R1 و R2 را می توان تا 2K افزایش داد تا صدا را کاهش داده و جهش بلندگو را کاهش دهد.

سوئیچ محدود از درایو دیسک کاملاً جا می شود ، گویی که به طور خاص برای جعبه ایجاد شده است (برای باز کردن کار می کند - وقتی درب را باز می کنید ، برق به برد تأمین می شود):

منابع سیستم عامل در فهرست ATTiny85MusicBox قرار دارند.

8 کیلوبایت مناسب است:
1) پخش کننده: 18000 هرتز، 4 کانال، Sine+Envelope، Pitch+12، فشرده سازی، ملودی ها را تک تک پخش می کند (آخری در EEPROM ذخیره می شود)
2) Yiruma - رودخانه در شما جریان دارد
3) فرانتس شوبرت – سرناد
4) P.I. چایکوفسکی "اکتبر"

نتیجه در ویدیو:

پیشرفتهای بعدی

در اصل، بازیکن را می توان بیشتر توسعه داد و آن را به یک پخش کننده تمام عیار Midi یا MOD رساند. من شخصا فکر می کنم که برای دریافت یک ملودی با کیفیت بالا، اتصال یک کارت SD و پخش هر فایل WAV از آن با موارد بسیار بیشتر آسان تر است. بهترین کیفیتچیزی که معمولاً با سنتز نرم افزار به دست می آید. و چنین پخش کننده ای در نرم افزار و سخت افزار بسیار ساده تر است. طاقچه hxMidiPlayer صدای خوبی را به پروژه های آماده اضافه می کند، زمانی که چند پایه باقی مانده و فضای کمی در فلش وجود دارد. در حال حاضر به شکل موجود خود "به خوبی" با این وظیفه کنار می آید.

من فکر می کنم این می تواند مسئله ایجاد انواع جعبه موسیقی / زنگ در AVR را ببندد :)

ادامه درس خیلی طول کشید که قابل درک است که باید به کار با کارت حافظه و فایل مسلط می شدم سیستم چربی. اما با این حال، این اتفاق افتاد، درس آماده است - در واقع، یک معجزه سال نو.

برای اینکه مقاله با اطلاعات زیاد نباشد، ساختار فرمت فایل wav را شرح نمی دهم. کافی است بگوییم که اگر فایلی را با نوعی ویرایشگر Hex باز کنید، 44 بایت اول شامل تمام اطلاعات مربوط به نوع فایل، نرخ نمونه برداری، تعداد کانال ها و غیره است. اگر نیاز به تجزیه و تحلیل فایل دارید، این مطلب را بخوانید. هدر و شما خوشحال خواهید شد.

داده های محموله از 44 بایت شروع می شود که اساساً شامل سطوح ولتاژی است که صدا را می سازد. قبلاً در قسمت آخر درس در مورد سطوح ولتاژ صحبت کردیم. بنابراین، همه چیز ساده است، باید این مراحل را در فرکانس نمونه برداری از فایل به بلندگو ارسال کنید.

چگونه از نظر فیزیکی بلندگو را تکان دهیم؟ شما باید این سطوح ولتاژ را با استفاده از PWM یا R2R خروجی بگیرید. در هر صورت، استفاده از آن بسیار ساده است، شماره را بخوانید، آن را در OCR یا PORTx قرار دهید. سپس بعد از مدتی مقدار بعدی را جایگزین کردم و تا آخر فایل ادامه دادم.

به عنوان مثال، یک فایل wav خاص، داده ها از بایت های 44=0x2C می آیند، عدد 0x80 در آنجا نوشته شده است، ما صدا را بازتولید می کنیم، به عنوان مثال با استفاده از PWM اولین تایمر، بنویسید OCR1A=0x80. فرض کنید فرکانس نمونه برداری 8 کیلوهرتز است، بنابراین وقفه باید روی همان فرکانس تنظیم شود. در وقفه، مقدار بعدی 0x85 را بعد از 1/8000 = 125 میکروثانیه جایگزین کنید.

چگونه وقفه را روی 8 کیلوهرتز تنظیم کنیم؟ به یاد داشته باشیم که اگر تایمر در فرکانس 250 کیلوهرتز کار می کند، باید رجیستر مقایسه وقفه (250/8)-1=31-1 یا 0x1E جایگزین شود. با PWM، همه چیز ساده است.

برای اینکه سیستم عامل کار کند، ما موافقت می کنیم که درایو فلش با استفاده از فایل PetitFat از درس 23.2 با فرمت FAT32 فرمت شود. فایل در فرمت wav، 8 کیلوهرتز یا 22.050 کیلوهرتز، مونو است. نام فایل 1.wav. بیایید سیستم عامل را تجزیه و تحلیل کنیم.

#عبارتند از #include "diskio.h" #include "pff.h" unsigned char buffer[ 512 ] ; /* بافری که اطلاعات از درایو فلش در آن کپی می شود */تعداد int unsigned volatile; // شمارنده داده کپی شدهقطع [TIM2_COMP] void timer2_comp_isr(void) //وقفه ای که در آن مقادیر جایگزین می شوند(OCR1A = بافر[ تعداد] ; // خروجی صدا به بلندگواگر (++ شمارش >= 512 ) // شمارنده را افزایش دهیدتعداد = 0 ; //اگر 512 ریست شود) void main(void) (unsigned int br; /* شمارنده خواندن/نوشتن فایل */ char unsigned buf = 0 ; //متغیر که مشخص می کند کدام قسمت از بافر خوانده می شود FATFS fs; /* فضای کاری (شیء سیستم فایل) برای درایوهای منطقی */ PORTB= 0x00 ; DDRB= 0x02 ; //پرش شیم ocr1a // مقداردهی اولیه تایمر/ شمارنده 1// منبع ساعت: ساعت سیستم // مقدار ساعت: 8000000 کیلوهرتز // حالت: Fast PWM top=0x00FF // خروجی OC1A: Non-Inv. TCCR1A= 0x81 ; TCCR1B= 0x09 ; TCNT1 = 0x00 ; OCR1A= 0x00 ; // مقداردهی اولیه تایمر/ شمارنده 2// منبع ساعت: ساعت سیستم // مقدار ساعت: 250000 کیلوهرتز // حالت: CTC top=OCR2 TCCR2= 0x0B ; TCNT2 = 0x00 ; //OCR2=0x1E; //تنظیم رجیستر مقایسه برای 8 کیلوهرتز OCR2= 0xA ; //برای 22 کیلوهرتز #asm("sei") // تایمر(ها)/ شمارشگر(ها) وقفه(های) مقداردهی اولیه if (disk_initialize() == 0) //درایو فلش را راه اندازی کنید( pf_mount(&fs) ; //کوه سیستم فایل pf_open("1.wav"); // یک تاپیک باز کنید pf_lseek(44); // نشانگر را به 44 منتقل کنید pf_read(buffer, 512,& br); //برای اولین بار 512 بایت را به یکباره قورت می دهیم TIMSK= 0x80 ; //روشن کردن موسیقی در حالی که (1) (اگر (! buf && count> 255 ) //اگر بیش از 255 بایت بازتولید شود،(pf_read(& buffer[ 0], 256,& br) ; //سپس اطلاعات را از درایو فلش در نیمه اول بافر می خوانیم buf= 1 ; اگر (بر< 256 ) //اگر بافر حاوی 256 مقدار نباشد، به معنای پایان فایل استزنگ تفريح ؛< 256 ) { pf_read(& buffer[ 256 ] , 256 ,& br) ; ) if (buf && count// قسمت دوم بافر را از درایو فلش بخوانید< 256 ) break ; } } TIMSK = 0x00 ; //глушим все pf_mount(0x00 ) ; buf = 0 ; اگر (بر// حجاب را از بین ببر

) در حالی که (1) ( ) #include "diskio.h" #include "pff.h" char buffer unsigned; /* بافری که اطلاعات از درایو فلش در آن کپی می شود */ volatile unsigned int count. // شمارنده وقفه داده های کپی شده void timer2_comp_isr(void) //وقفه ای که در آن مقادیر جایگزین می شوند (OCR1A = بافر؛ //صدای خروجی به بلندگو اگر (++ شمارش >= 512) //افزایش شمارنده شمارنده = 0; //if 512 reset ) void main(void) (unsigned int br; /* file read/write counter */ unsigned char buf = 0; //متغیر که تعیین می کند کدام قسمت از بافر FATFS خوانده می شود؛ /* در حال کار ناحیه (شیء سیستم فایل) برای درایوهای منطقی */ PORTB=0x00; Fast PWM top=0x00FF // OC1A output: Non-Inv TCCR1A=0x00 TCNT1=0x00; OCR2 TCCR2=0x00; (s) مقداردهی اولیه if(disk_initialize()==0) //initialize flash drive ( pf_mount(&fs); // سیستم فایل را نصب کنید pf_open("1.wav"); //باز کردن شاخه pf_lseek(44); // نشانگر را به 44 pf_read منتقل کنید (بافر، 512،&br); //برای اولین بار 512 بایت را به یکباره قورت می دهیم TIMSK=0x80; //موزیک را روشن کنید while(1) ( if(!buf && count>255) //اگر بیش از 255 بایت پخش شده باشد، ( pf_read(&buffer, 256,&br);//سپس اطلاعات را از فلش بخوانید درایو به نیمه اول بافر باف=1 ;< 256) //если буфер не содержит 256 значений значит конец файла break; } if(buf && count<256) { pf_read(&buffer, 256,&br); // читаем во вторую часть буфера с флешки buf = 0; if (br < 256) break; } } TIMSK = 0x00; //глушим все pf_mount(0x00); //демонтируем фат } while (1) { } }

برای بررسی، ما یک بلندگو را از طریق یک خازن 100uF به پایه OCR1A، "+" به پایه میکروکنترلر، "-" به بلندگو متصل می کنیم. "-" بلندگو به زمین، "+" به خازن.

انتظار سیگنال بلند را در خروجی نداشته باشید. این به وضوح در ویدیو قابل مشاهده است. برای تست، خروس را با 8 کیلوهرتز و آهنگ را با 22 کیلوهرتز بارگذاری کردم.

کسانی که مایلند می توانند با خیال راحت فرکانس تایمر 2 را برای پخش فایل های 44 کیلوهرتز افزایش دهند. تو ویدیو صدا ضعیفه و کیفیتش پایینه ولی در واقع به خاطر اینه که با دوربین فیلمبرداری کردم.

من همچنین مطالبی را ارسال می کنم که با مهربانی توسط Apparatchik ارائه شده است - کد منبع برای GCC، که سیستم عامل CAVR از آن نوشته شده است.

و ویدیو با پخش 44 کیلوهرتز.

از این فرصت استفاده می‌کنم و سال نو را به همه تبریک می‌گویم، امیدوارم همه سیستم‌افزارها و دستگاه‌ها برای شما کار کنند :)

پروژه پخش کننده wav در Atmega8

من یک ماژول نرم افزاری نوشتم که به شما امکان می دهد عملکرد پخش ملودی ها یا دنباله های صدا را به تقریباً هر پروژه ای در میکروکنترلر AVR اضافه کنید.

ویژگی های ماژول:

ادغام آسان با یک پروژه آماده

فقط از تایمر 8 بیتی t2 استفاده می شود، در حالی که امکان استفاده از آن برای نظرسنجی یا تشکیل فواصل زمانی وجود دارد.

ماژول تقریباً برای هر فرکانس مولد ساعت قابل تنظیم است

گام نت ها به صورت ثابت های نمادین (C0، A2 و غیره) یا بر حسب هرتز مشخص می شود.

مدت زمان ها به صورت استاندارد (چهارم، هشتم و غیره) یا بر حسب میلی ثانیه مشخص می شوند.

امکان تنظیم سرعت پخش ملودی و تعداد تکرارهای آن وجود دارد

در حین پخش، ملودی را می توان مکث کرد


اتصال یک ماژول صدا

1. تمام فایل های ماژول (tone.h، sound.h، sound.c) را در پوشه پروژه کپی کنید.

2. فایل sound.c را به پروژه وصل کنید.

برای IAR `a – در پنجره فضای کاری کلیک راست کرده و Add > Add Files را انتخاب کنید…

برای WINAVR تقریباً یکسان است، فقط sound.c باید به makefile اضافه شود:

SRC = $(TARGET).c sound.c

3. فایل هدر sound.h را در ماژول مربوطه قرار دهید. برای مثال در main.c

#شامل "sound.h"

4. تنظیمات ماژول را در فایل sound.h تنظیم کنید

//اگر نظر بدهید، مدت زمان یادداشت ها خواهد بود

//از BPM مشخص شده در ملودی محاسبه می شود

//اگر چپ، سپس از مقدار مشخص شده در زیر

//#define SOUND_BPM 24

//فرکانس ساعت μ

#define SOUND_F_CPU 16U

//خروجی میکروکنترلری که صدا روی آن تولید خواهد شد

#define PORT_SOUND PORTB

#define PINX_SOUND 0

//تعداد ملودی های مشخص شده.

#define SOUND_AMOUNT_MELODY 4

5. ملودی های خود را به sound.c اضافه کنید و نام ملودی ها را در آرایه ملودی بنویسید.

اضافه کردن آهنگ های زنگ

ملودی آرایه ای از اعداد 16 بیتی است و ساختار زیر را دارد

BPM (نت‌های چهارم در دقیقه)ثابتی است که برای محاسبه مدت نت ها استفاده می شود و سرعت پخش ملودی را تعیین می کند.

BPM می تواند از 1 تا 24 متغیر باشد که به ترتیب مربوط به 10 و 240 نت در دقیقه است.

اگر مدت زمان نت ها/صداها بر حسب میلی ثانیه مشخص شده باشد، BPM نوشته شده در آرایه باید برابر با 1 باشد.

اگر ثابت SOUND_BPM در فایل هدر sound.h بیان شود، آنگاه مدت زمان یادداشت ها در طول اجرای برنامه بر اساس BPM مشخص شده در آرایه محاسبه می شود. اگر SOUND_BPM نظر داده نشود، مدت زمان نت ها بر اساس مقدار این ثابت در مرحله کامپایل محاسبه می شود و همه ملودی ها با یک سرعت پخش می شوند. این کارکرد را محدود می کند، اما چند بایت کد را ذخیره می کند.

تعداد تکرار.می تواند مقادیر 1 ... 254 و LOOP (255) را بگیرد. LOOP - به این معنی است که ملودی تا زمانی که دستور SOUND_STOP یا SOUND_PAUSE داده شود بی انتها تکرار می شود.

توجه به مدت زمان- زمانی که در طی آن یک آهنگ صدای داده شده تولید می شود یا یک مکث حفظ می شود. می توان آن را در ms، با استفاده از ماکرو ms(x) یا به عنوان مقادیر نت استاندارد - نت هشتم، نت شانزدهم و غیره مشخص کرد. در زیر لیستی از مدت زمان پشتیبانی شده است. اگر نیاز به مدت‌های عجیب و غریب وجود دارد، همیشه می‌توانید آنها را در فایل tone.h اضافه کنید

n1 - یادداشت کامل

n2 - نیم نت

n4 - یک چهارم

n8 - هشتم

n3 - سه قلو هشتم

n16 - شانزدهم

n6 - sextole

n32 - سی و دوم

زمین را یادداشت کنیدبا استفاده از ثابت های نمادین شرح داده شده در فایل tone.h، برای مثال C2، A1 و غیره مشخص می شود. همچنین، با استفاده از ماکرو f(x) می توان گام نت ها را بر حسب هرتز مشخص کرد.

این برنامه محدودیت هایی در حداقل و حداکثر فرکانس صدا دارد!

نشانگر پایان ملودی.مقدار آخرین عنصر آرایه باید صفر باشد.

با استفاده از ماژول صدا

در ابتدای main، باید تابع SOUND_Init() را فراخوانی کنید. این تابع پایه خروجی میکروکنترلر را تنظیم می کند، تایمر T2 را پیکربندی می کند و متغیرهای ماژول را مقداردهی اولیه می کند.

سپس باید پرچم فعال کردن وقفه را تنظیم کنید - __enable_interrupt()، زیرا ماژول از سرریز تایمر T2 و وقفه های تصادفی استفاده می کند.

پس از این، می توانید شروع به پخش ملودی کنید.

به عنوان مثال، مانند این:

SOUND_SetSong(2);

SOUND_Com(SOUND_PLAY)؛ //نواختن ملودی

// نشانگر را روی ملودی دوم تنظیم کنید

//و شروع به پخش کنید

SOUND_PlaySong(2);

پخش ملودی را می توان در هر زمان با صدور فرمان SOUND_STOP متوقف کرد.
همچنین می توانید ملودی را با استفاده از دستور SOUND_PAUSE متوقف کنید. صدور بعدی فرمان SOUND_PLAY پخش ملودی را از نقطه ای که متوقف شده بود از سر می گیرد.

در اصل، این قابلیت به ویژه مورد نیاز نیست (من همین الان آن را درست کردم) و هنگام کار با ماژول، عملکرد SOUND_PlaySong (unsigned char numSong) کافی است.

فایل ها

نمونه های استفاده از ماژول صدا را می توانید از لینک های زیر دانلود کنید. من نموداری نکشیدم زیرا همه چیز در آنجا ساده است. به پین ​​PB0 متصل می شود، دکمه شروع ملودی ها به پین ​​PD3 متصل می شود. 4 ملودی در پروژه ها تعریف شده است. با فشار دادن دکمه هر بار یک ملودی جدید شروع می شود. از میکروکنترلر atmega8535 استفاده شده است. در ابتدا می خواستم با یک پروژه با چهار دکمه - PLAY، STOP، PAUSE و NEXT زحمت بکشم، اما بعد فکر کردم که این کار غیر ضروری است.

PS: ماژول تحت آزمایش گسترده قرار نگرفته است و "همانطور که هست" ارائه می شود. اگر پیشنهادهای منطقی وجود دارد، آن را نهایی کنیم.

در این مقاله به نحوه نواختن آهنگ ها و نحوه اجرای یک ملودی مونوفونیک خواهیم پرداخت.

آماده شدن برای کار

برنامه دو آرایه را اعلام می کند. آرایه با یادداشت ها یادداشتشامل یک لیست ساده از یادداشت ها است. این نت ها با مدت زمان صدا در آرایه مطابقت دارند می زند. مدت زمان در موسیقی با تقسیم کننده یک نت نسبت به کل نت تعیین می شود. مقدار در نظر گرفته شده به عنوان یک یادداشت کل است 255 . از تقسیم این عدد نصف، چهارم، هشتم به دست می آید.
لطفا توجه داشته باشید که مدت زمان نت اول با تقسیم 255 بر توان دو به دست نمی آید. در اینجا شما باید به تئوری موسیقی بروید. نت های ملودی اصلی قابل مشاهده است. این نت ها به صورت سه قلو ترکیب می شوند. هنگامی که به این ترتیب ترکیب می شوند، سه نت هشتم مانند یک نت چهارم به نظر می رسند. بنابراین مدت نسبی آنها 21 است.
کاربر همچنین باید به صراحت تعداد یادداشت ها را در ترتیب با دستورالعمل مشخص کند:

# SEQU_SIZE 19 را تعریف کنید

در برنامه اصلی، اول از همه، آرایه های فرکانس دوباره محاسبه می شود و مدت زمان به دوره های سیگنال و مدت زمان یادداشت ها محاسبه می شود.
با دوره های سیگنال (آرایه سیگنال_دوره) ساده است. برای بدست آوردن مدت زمان پریود بر حسب میکروثانیه، کافی است 1,000,000 را بر فرکانس سیگنال تقسیم کنید.
برای محاسبه مدت زمان مطلق نت ها باید تمپوی اثر موسیقی مشخص شود. این کار با بخشنامه انجام می شود

# TEMPO 108 را تعریف کنید

تمپو در موسیقی تعداد نت های یک چهارم در دقیقه است. در صف

# تعریف WHOLE_NOTE_DUR 240000 / TEMPO

مدت زمان یک نت کامل بر حسب میلی ثانیه محاسبه می شود. اکنون کافی است مقادیر نسبی را از آرایه با استفاده از فرمول دوباره محاسبه کنید می زندبه آرایه مطلق note_duration.
در حلقه اصلی، متغیر گذشت_زمانپس از هر دوره از سیگنال پخش شده به مدت این دوره افزایش می یابد تا زمانی که از مدت زمان نت بیشتر شود. توجه به این مدخل ارزش دارد:

while(زمان_گذشته< 1000 * ((uint32_t) note_duration[ i] ) )

متغیر گذشت_زمان 32 بیتی و عناصر آرایه یادداشت_مدت 16 بیتی. اگر یک عدد 16 بیتی در 1000 ضرب شود، سرریز تضمین شده و متغیر گذشت_زمانبا زباله مقایسه خواهد شد اصلاح کننده (uint32_t)یک عنصر آرایه را تبدیل می کند notes_duration[i]در یک عدد 32 بیتی هیچ سرریزی وجود ندارد.
شما می توانید ویژگی دیگری را در حلقه صوتی مشاهده کنید. امکان استفاده از عملکرد وجود نخواهد داشت _delay_us()، زیرا آرگومان آن نمی تواند متغیر باشد.
برای ایجاد چنین تاخیرهایی، از تابع استفاده کنید VarDelay_us(). در آن، یک حلقه با تاخیر 1 میکرو ثانیه به تعداد مشخصی بارها پیمایش می شود.

void VarDelay_us(uint32_t takt) ( while (takt- - ) ( _delay_us(1 ; ) )

هنگام پخش یک ملودی، از دو تاخیر دیگر استفاده می شود. اگر نت‌ها بدون مکث پخش شوند، در یکی ادغام می‌شوند. برای انجام این کار، یک تاخیر 1 میلی ثانیه بین آنها درج می شود که توسط دستورالعمل مشخص شده است:

# تعریف NOTES_PAUSE 1

پس از هر چرخه کامل پخش ملودی، برنامه به مدت 1 ثانیه مکث می کند و دوباره شروع به پخش می کند.
در نتیجه، کدی دریافت کردیم که در آن به راحتی می توان سرعت را تغییر داد، مدت زمان را تنظیم کرد یا ملودی را کاملاً بازنویسی کرد. برای انجام این کار کافی است فقط بخشی از برنامه با دستورالعمل ها و اعلان های متغیر تبدیل شود.

وظایف فردی

  1. در ملودی پیشنهادی، تمپو را تغییر دهید و بین تکرارها 5 ثانیه مکث کنید.
  2. عناصر آرایه می زندفقط مقادیر 0 تا 255 را بپذیرید. عرض بیت عناصر آرایه را تغییر دهید و به خروجی کامپایلر نگاه کنید تا ببینید که چگونه بر میزان حافظه اشغال شده توسط برنامه تأثیر می گذارد.
  3. حالا سعی کنید ملودی را خودتان تغییر دهید. به عنوان مثال، در اینجا "امپریال مارس" از همان فیلم است: یادداشت های int = ( A4, R, A4, R, A4, R, F4, R, C5, R, A4, R, F4, R, C5, R, A4، R، E5، R، E5، R، E5، R، F5، R، C5، R، G5، R، F5، R، C5، R، A4، R). ضربات int = ( 50 , 20 , 50 , 20 , 50 , 20 , 40 , 5 , 20 , 5 , 60 , 10 , 40 , 5 , 20 , 5 , 60 , 80 , 2 , 50 , 50 20، 40، 5، 20

    اگر ماشین شما آژیر صوتی نصب نکرده است و هنوز نمی توانید تصمیم بگیرید کدام یک را بخرید و نصب کنید، این مقاله فقط برای شماست. اگر می‌توانید همه آن‌ها را خودتان به روشی نسبتاً ساده مونتاژ کنید، چرا سیستم‌های هشدار گران قیمت بخرید؟

    من دو تا از اینها را ارائه می کنم مدارهای سادهدر میکروکنترلرهای AVR ATmega8 و Attiny2313 یا بهتر است بگوییم همین مدار برای کار روی این دو میکروکنترلر به سادگی پیاده سازی شده است. به هر حال، در بایگانی دو نسخه از سیستم عامل برای میکروکنترلر Atmega8 پیدا خواهید کرد، که اولی صدایی شبیه به دزدگیر ماشینو صدای دوم شبیه دزدگیر امنیتی ساختمان (سیگنال سریع و تیز) است.

    شما می توانید تمام سیستم عامل های زیر را در بایگانی دانلود کنید (همه آنها امضا شده اند)، در آرشیو همچنین شبیه سازی مدارها را در Proteus خواهید یافت، به این معنی که پس از گوش دادن به تمام آهنگ ها می توانید از لیست آنچه را که بیشتر دوست دارید انتخاب کنید. .

    در زیر نمودار سیگنالینگ Atmega8 آمده است

    لیست قطعات رادیویی مورد استفاده در مدار Atmega8

    U1- میکروکنترلر AVR 8 بیت ATmega8-16PU، تعداد. 1،
    R1- مقاومت با مقدار اسمی 47 اهم، شماره. 1،
    R2، R3 - مقاومت با مقدار اسمی 270 اهم، شماره. 2،
    D2، D3-LED، شماره 2،
    LS1-speaker, no. 1،
    سنسور S1.

    و در مدار سیگنالینگ در Attiny2313 فقط MK تغییر کرده است.
    U1- میکروکنترلر AVR 8 بیتی ATtiny2313-20PU، شماره. 1.

    تخته مدار چاپیبرای Atmega8 به شکل زیر است:

    همانطور که می بینید مدار بسیار ساده است، فقط یک میکروکنترلر، 3 مقاومت، 2 LED و یک بلندگو دیگر وجود دارد. به جای دکمه، می توانید از یک سوئیچ نی یا تماس دیگر استفاده کنید.

    اصل عملیات به شرح زیر است. به محض اینکه برق را اعمال می کنیم، ال ای دی (در مدار D3) بلافاصله روشن می شود یا شروع به چشمک زدن می کند (بسته به سیستم عامل) و اگر سنسور را لمس نکنیم، آلارم بی صدا می شود. حالا اگه سنسور فعال بشه آژیر هم کار میکنه LED هم چشمک میزنه ولی D2.

    اگر می خواهید چراغ های جلوی خودرو هنگام کار کردن زنگ چشمک بزنند، برای انجام این کار باید پین میکروکنترلر 24 PC1 را از طریق ترانزیستور به رله و خود رله را به چراغ های جلو وصل کنید. برای خاموش کردن آژیر، باید دستگاه را خاموش و دوباره روشن کنید یا به سادگی دکمه را فشار دهید. برای کار با میکروکنترلر به یک نوسان ساز داخلی 8 مگاهرتز نیاز دارید.

    اگر می خواهید صدای زنگ هشدار را به نحوی تقویت کنید، می توانید یک تقویت کننده با ترانزیستور جمع آوری کنید و آن را به مدار متصل کنید. این دقیقاً همان کاری است که من انجام دادم، اما آن را در این نمودار نشان ندادم.

    بیایید به مدار Attiny 2313 برویم، همانطور که قبلاً گفتم، تمام جزئیات و اصل کار یکسان است، فقط MK تغییر کرده است و در نتیجه این میکروکنترلر از طریق یک کار می کند نوسان ساز داخلی 4 مگاهرتز، اگرچه می توان آن را با فرکانس 1 مگاهرتز فلش کرد.

    در زیر نمودار اتصال قبلاً در Attiny2313 است

    برای این MK من فقط یک نسخه از سیستم عامل نوشتم، همه چیز را روی برد مدار مونتاژ کردم، آن را بررسی کردم، همه چیز خوب کار می کند.
    و فیوزها باید مطابق شکل زیر تنظیم شوند:





بالا