تبلیغات
باران الکترونیک - تولید صدای دیجیتال ‏Synthetic sounds
یکشنبه 18 بهمن 1394  01:03 ق.ظ
نوع مطلب: (DSP ،برنامه نوسی C ،) توسط: امیرحسین رستمی

هدف از این مقاله تبدیل یک کد ‏floating-poing‏ به ‏fixed-point‏ و مقایسه این دو کد از نظر زمان اجرا ‏می باشد. برای این منظور از کد تولید صدای ناقوس در ‏MATLAB‏ استفاده شد و آن را در پردازنده ‏DSP‏ به ‏شماره قطعه ‏TMS320C5509A‏ پیاده سازی کردیم.‏
می توانید صدای نهایی را از لینک زیر دریافت کنید:
پیاده سازی پروژه نهایی روی پردازنده  DSP در ویدیوی زیر نشان داده شده است:
 
[http://www.aparat.com/v/dsigR]

صوت دیجیتال
 
از کاربردهای صوت دیجیتال می توان به تولید صدا و افکت گذاری روی صدا اشاره کرد. برای تولید صدا به صورت دیجیتال ‏روش های زیادی وجود دارد که عبارتند از:‏
  • مدولاسیون فرکانسی (‏Frequency Modulation‏)‏
                     در این روش از یک موج فرکانسی پیچیده برای تولید صدا به کار می رود‎.‎‏ فرمول کلی به صورت زیر می باشد:‏
    sound = A sin(αt+Isin(βt))‎
 
  • جدول موج ‏Wavetable synthesis
             در این روش صدا از نمونه برداری صدای دستگاه های موسیقی ساخته می شود.‏
 
  • افزایشی ‏Additive synthesis
            در این روش صدا نهایی از ترکیب صداهای ساده تر و کوتاه تر ساخته می¬شود.‏
 
  • کاهشی ‏Subtractive synthesis
              در این روش از یک شکل موج پیچیده (مانند دندان اره ای) به عنوان ورودی استفاده می شود سپس با فیلتر کردن سعی در ‏تولید صدای نهایی می شود.‏
 
  • دانه ای ‏Granular Synthesis
             در این روش از قطعات کوتاه برای ساخت صدای جدید استفاده می شود.‏
 
  • مدل فیزیکی ‏Physical Modelling
             در این روش صدای تولید شده از دستگاه با مدل کردن شکل دستگاه و پیدا کردن معادله موج (ریاضیات مهندسی) ساخته ‏می شود.‏
 
  • مبتنی بر نمونه ‏Sample-based synthesis
             در این روش از ذخیره و بازپخش صدای ضبط شده استفاده می شود. معمولا صدای ضبط شده کوتاه است و همراه با پردازش ‏صوت می باشد.‏

تولید صدا زنگ ناقوس با استفاده از روش ‏FM
 
کد متلب
 
کد ‏MATLAB‏ برای تولید صدای زنگ به صورت زیر می باشد:‏

% bell.m

%

% A Matlab script to compute a bell-like sound using frequency modulation.

%

% by Gary Scavone, McGill University, 2004.

  

% Signal parameters

fs = 22050;

T = 1/fs;

dur = 4.0;

t = 0:T:dur;

T60 = 1.0;

env = 0.95*exp(-t/T60);

  

% FM parameters

fc = 200;

fm = 280;

Imax = 10;

I = Imax.*env;

  

y = env.*sin(2*pi*fc*t + I.*sin(2*pi*fm*t));

plot(t, y);

 

sound(y, fs);


wavwrite(y,fs,16,'sound_bell_float')

% dospectrum = input('\nPlot spectrum? Y/[N]:\n\n', 's');

 

% if dospectrum == 'y',

  specgram(y, 512, fs, [], 256)

% end


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

صدای ناقوس در حوزه زمان

نمودار زمان-فرکانس در ادامه نشان داده شده است:‏

نمودار زمان فرکانس صدای ناقوس
فایل متلب به همراه فرمت ‏wav‏ برای دریافت در انتها قرار داده شده است.‏
 
کد ‏C‏ در محیط ‏Visual Studio
 
همین کد متلب را به کد ‏C‏ تبدیل می کنیم. برای این کار به جای دستورات متلب معادل ‏C‏ را قرار دادیم. ‏برنامه را در این قدم به همان صورت اعشاری یا ‏float‏ می نویسیم. تنها تفاوتی که این جا وجود دارد این است ‏که نمی تواند با کد ‏C‏ صدا تولید کرد و از بلندگوی کامپیوتر پخش کرد (با ‏C#‎‏ کار سه صوته با ‏C‏ نمی دونم). ‏خوب راه حل چیست؟
نه اشتباه گفتید. راهش این است که خروجی نهایی را در یک فایل ذخیره کنیم. سپس با استفاده از ‏MATLAB‏ این فایل را پخش کنیم. نتیجه نهایی نباید تفاوتی با کد اصلی متلب داشته باشد. با استفاده از ‏سه تابع ‏fopen، ‏fwrite‏ و ‏fclose‏ این کار را انجام می دهیم:‏


#include <stdlib.h>

#include <stdio.h>

#include <math.h>

 

#define LX 400

 

short FS  = 22050;

short dur = 4.0;

float PI =  3.1416f;

// FM parameters

short Imax = 10;

short fc =  200;

short fm  = 280;

short T60 = 1.0;

  

FILE *fp_out,*fp_exp,*fp_y;

char x_out[LX*2];

 

char y_name[160] = "..\\y_vs_float.bin";

//Signal parameters

  

float env[LX];

float I[LX];

float y_bell[LX];

float theta[LX];

 

int main(void)

  {

      int n_prd1,n_prd2;

      int i,n1=0,n2=0;

      long loop=0;

      unsigned short of;

      float fs_fix;

 

      float T = 1.0f/FS;

 

      long NX = FS*dur;

 

      fs_fix= 32768.0f/(NX);

      n_prd1 = (FS / fm) >> 1;

      n_prd2 = (fc / fm) >> 1;

      //open file to write result

      if ((fp_y = fopen(y_name,"wb")) == NULL){

            fprintf(stderr, "  ERROR: cannot read file %s.\n", y_name);

            exit(0);

      }

 

      while(loop < NX - LX)

      {

            for (i=0; i<LX ;i++)

                  env[i] = (0.95f) * exp((float)-(i+loop)*T);

 

            for (i=0; i<LX ;i++)

                  I[i]= Imax * env[i];

 

            for (i=0; i<LX ;i++)

                  theta[i] = sin(2*PI*fm*(i+loop)*T);

        

            for (i=0; i<LX ;i++)

                  theta[i] = ((2*PI*fc*(i+loop)*T) ) + (I[i]*theta[i]);

 

            for (i=0; i<LX ;i++)

                  theta[i] = sin(theta[i]);

           

            for (i=0; i<LX ;i++)

                  y_bell[i] = env[i] * theta[i];

           

            fwrite(y_bell, sizeof(float), LX, fp_y);

 

            loop = loop + LX ;

      }

     

      fclose(fp_y);

 

      return 0;

}

برای این که از تابع­ های سینوس و نمایی استفاده کردیم هدر فایل math.h را به اول برنامه اضافه کردیم. هدر فایل­های stdlib و stdio برای خواندن و یا نوشتن در فایل لازم می­ باشند.

نکته جالبی که در این­جا  وجود دارد این است که مانند متلب از متغییرهای با طول زیاد استفاده نشده است (طول y در برنامه متلب بیش از 88000 می­ شود) به جای آن طول متغییرها 400 در نظر گرفته شده است. با هر بار اجرای تابع 400 داده تولید می ­شود و در فایل ذخیره می ­شود.  دوباره این کار تکرار می ­شود تا در نهایت 88000 داده محاسبه شود. این کار به صورت معادل در DSP روی می ­دهد. دلیل اصلی این است که اگر بخواهیم چند متغییر با طول 88000 در DSP تعریف کنیم حافظه­ای باقی نمی­ ماند (خونه خاله نیست که هر چقدر متغییر خواستیم با هر طولی بتوانیم تعریف کنیم). در DSP می­خواهیم صدا به صورت real-time پردازش شود و در خروجی پخش شود و تاخیری نداشته باشیم. برای این منظور ابتدا تعداد محدودی نمونه مثل 200 نمونه را محاسبه می ­کنیم و به خروجی می ­فرستیم سپس قبل از این که نوبت 200 نمونه بعدی برسد DSP آن ها را محاسبه می­ کند همین طور تا آخر. در نهایت یک صدای پیوسته از بلندگوی DSP پخش می­ شود. این قسمت برعکس متلب می ­باشد. شما روی اجرا کلیک می­ کنید. مدتی طول می ­کشد تا نمونه ­ها محاسبه شوند سپس از بلندگو صدا پخش می­ شود.

کد متلب برای پخش صدای floting-point

برای پخش صدای فایل y_vs_float.bin در متلب از برنامه زیر استفاده کنید:

% ---------------------------

% sound_bin_float.m

% Author : Amirossein rostami

% ---------------------------

% Sampling frequency

Fs = 22050;

% read from file

fid = fopen('y_ccs_float.bin');

dataout = fread(fid,'float');

fclose(fid);

 

yout=dataout;

plot(dataout)

% play sound

sound(yout,Fs);

% Write sound in a wav file

% play it with windows media player

wavwrite(yout,Fs,16,'sound_bell_fix')


کد C floating-point برای DSP در نرم ­افزار CCS

 

کد ممیز شناور در CCS مانند Visual Studio می­ باشد. تنها تغییر در قسمت نوشتن در فایل می ­باشد. به پوشه پروژه برای دیدن تغییر مراجعه نمایید.

 

کد fixed-point C برای DSP در نرم ­افزار CCS

  

همان طور که می دانیم­ پردازنده ­های DSP ممیز ثابت ضرب صحیح را در یک کلاک انجام می ­دهند، اما ضرب اعشاری تعداد زیادی کلاک طول می کشد. در این قسمت هدف تبدیل برنامه floating-point به fixed-point می­ باشد تا MIPS برنامه را کاهش دهیم. برای این کار تغییرات زیر را در برنامه اصلی لحاظ کردیم:

1)     عدد پی

        به جای تقسیم بر پی در برنامه از تقسم بر 3 استفاده کردم.

2)     فرکانس نمونه برداری

       در برنامه اصلی فرکانس نمونه برداری fs = 22050 می­ باشد که زمان نمونه برداری Ts از معکوس این مقدار به دست می ­آید. برای تبدیل این                عدد به فرمت Q15 آن را در 215 ضرب می ­کنیم:

Ts=215×1/FS=1.48≈1‎

       با دقت 16 بیت Ts به 1 گرد می ­شود. به عبارت دیگر فرکانس نمونه برداری را fs = 32678‏ ‏در نظر گرفتیم.

برای ادامه مطلب به فایل PDF که در ادامه آمده است مراجعه کنید.

پروژه کامل CCS، MATLAB و VS در ادامه برای دانلود قرار داده شده است.


دانلود مقاله کامل به فرمت PDF

دانلود برنامه های کامل متلب

دانلود پروژه کامل code composer 3

دانلود پروژه کامل Visual Studio

دانلود صدای ناقوس 1

دانلود صدای ناقوس 2


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