Код за синусоидно помитане

Качено от mic на Sat, 06/30/2018 - 21:53

Пробвам различни синусоидни помитания за да ги използвам в импулсни ривърби. Мисля, че ще е полезно да покажа кода в Java за създаването на един кратък файл уейв с едно синусоидно помитане. Кодът е прост, но е интересен. Интересен е не само защото създава едно синусоидно помитане, но защото и показва структурата на просите файлове уейв. За програмистите, които започват с DSP и искат да четат или пишат файлове уейв, може да е полезно.

Това не е най-елегантния код, но лесно се разбира.

Файлове с произволен достъп

Файловете с произволен достъп не са нужни в този малък код, но осъществяването на файлове уейв с произволен достъп е добра идея. Това позволява да прескачаме парчетата RIFF и уейв, от които не се нуждаем. Това също позволява да се местим напред и назад в данните с аудио в парчето данни във файла уейв, като при превъртането напред и назад.

Данните уейв

Данните във файловете уейв – данните за аудио и данните за формата – се запазват, като най-маловажния байт се записва пръв и най-важния байт се записва последен ("little endian"). Тъй като не можем да гарантираме, че всички операционни системи ще записват числата с правилния ред на байтовете, трябват ни функции, които да записват с правилния ред на байтовете.

По-точно, трябва да можем да записваме цели числа от четири байта и цели числа от два байта.

public static void writeInt(RandomAccessFile file, long value) throws IOException
{
   long b0 = value & 0x000000ff;
   long b1 = (value & 0x0000ff00) >> 8;
   long b2 = (value & 0x00ff0000) >> 16;
   long b3 = (value & 0xff000000) >> 24;
   file.writeByte((byte) b0);
   file.writeByte((byte) b1);
   file.writeByte((byte) b2);
   file.writeByte((byte) b3);
}

public static void writeShort(RandomAccessFile file, int value) throws IOException
{
   int b0 = value & 0x000000ff;
   int b1 = (value & 0x0000ff00) >> 8;
   file.writeByte((byte) b0);
   file.writeByte((byte) b1);
}

Синусоидно помитане

Кодът за създаването на синусоидното помитане е по-долу. Ето и стъпките.

  • Създаваме едно синусоидно помитане, което помита честотите между 50 Hz и 1000 Hz в 1 секунда и слагаме резултата в един файл уейв с пробната честота 44.1 KHz и пробната резолюция 16 бита. Затова имаме и началните декларации.
  • Започваме, като записваме идентификацията "RIFF" за файловете RIFF.
  • След това записваме размера на файла RIFF. Размерът на файла RIFF включва: 1) 4 байта за под-идентификацията "WAVE"; 2) 4 байта за идентификацията "fmt "; 3) 4 байта за размера на парчето формат; 4) 16 байта за самото парче формат (размера на парчето формат е 16 байта, защото не броим размера на идентификацията и на размера на парчето формат); 5) 4 байта за идентификацията "data"; 6) samplingrate * channels * samplingresolution * T / 8 байта за данните за аудио.
  • Записваме под-идентификацията "WAVE" за да отбележим, че този файл RIFF е файл WAVE.
  • Записваме идентификацията на парчето формат.
  • Записваме размера на парчето формат (без 4 байта за идентификацията и 4 байта за размера).
  • Записваме различните части на парчето формат. Ще запазваме данни PCM и затова кода за компресиране е 1. Останалото е броя на каналите, пробната честота, средния брой на байтовете в секунда, размера на семплите за всички канали заедно ("block align") и броя на значителните бита в семплите (пробната резолюция).
  • Записваме идентификацията на парчето данни.
  • Записваме данните за аудио.

Тук има две синусоидни помитания – едно линейно (коментирано) и едно експоненциално.

Стойността на синусоидното помитане при всеки от семплите първо ще бъде между -1 и 1. Увеличаваме го до две трети от диапазона, позволен от записа с 16 бита (този избор от 2/3 е случаен и може да бъде променен). Когато записваме получените стойности, не използваме writeShort, защото writeShort по принцип е създадено да записва цели числа от два байта без знак, а пък данните за аудио имат знак (те са положителни или отрицателни).

Можеш да чуеш получените файлове уейв в темата в речника Синусоидно помитане.

try
{
   float f0 = 50;
   float f1 = 1000;
   float T = 1;
   float samplingrate = 44100F;
   int samplingresolution = 16;
   int channels = 1;

   // open a wave file
   RandomAccessFile file = new RandomAccessFile("chirp.wav", "rw");

   // write the header
   file.seek(0);
   file.writeBytes("RIFF");
   writeInt(file, (int) (4 + 4 + 4 + 16 + 4 + samplingrate * channels *
       samplingresolution * T / 8));
   file.writeBytes("WAVE");

   // write the format chunk
   file.writeBytes("fmt ");
   writeInt(file, 16L); // size of format chunk
   writeShort(file, 1); // format type
   writeShort(file, channels);
   writeInt(file, (int) samplingrate);
   writeInt(file, ((int) samplingrate * channels * samplingresolution) / 8);
   writeShort(file, (channels * samplingresolution) / 8);
   writeShort(file, samplingresolution);

   // write the data chunk
   file.writeBytes("data");
   writeInt(file, (int) (samplingrate * channels * samplingresolution * T / 8));

   // write the sine sweep data
   for(int i = 0; i    {
       double t = (double) i / samplingrate;
       //double value = Math.sin(2D * Math.PI
           * (f0 * t + (f1 - f0) * t * t / (2 * T)));
       double value = Math.sin(2D * Math.PI * f0 * T
           * (Math.pow(f1 / f0, t / T) - 1) / (Math.log(f1 / f0)));
       int ivalue = (int) Math.min(Math.max(value * Short.MAX_VALUE * 2 / 3,
           Short.MIN_VALUE), Short.MAX_VALUE);
       file.writeByte((byte) (ivalue & 0xff));
       file.writeByte((byte) (ivalue >>> 8 & 0xff));
   }

   file.close();
}
catch (IOException e)
{
   System.out.println("Exception: " + e);
}

автори: mic

Добави нов коментар

Filtered HTML

  • Freelinking helps you easily create HTML links. Links take the form of [[indicator:target|Title]]. By default (no indicator): Click to view a local node.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.