Как звук представлен цифрами? - PullRequest
44 голосов
/ 09 апреля 2009

Мне нравится думать о том, как все может быть и представлено числами. Например, открытый текст представлен кодом, подобным ASCII, а изображения представлены значениями RGB. Это самые простые способы представления текста и изображений.

Как проще всего представить звук цифрами? Я хочу научиться писать программы, работающие со звуком, и подумал, что это будет хорошим началом. Хотя я не могу найти хороших объяснений в Интернете.

Ответы [ 10 ]

89 голосов
/ 09 апреля 2009

Физически, как вы, наверное, знаете, звук - это вибрация. Как правило, мы говорить о колебаниях воздуха между примерно 20 Гц и 20000 Гц. Это означает, что воздух движется туда-сюда от 20 до 20000 раз за второй.

Если вы измеряете эту вибрацию и преобразуете ее в электрический сигнал (скажем, с помощью микрофона), вы получите электрический сигнал с напряжение меняется в той же форме волны, что и звук. В нашем чистом тоне гипотетически, этот сигнал будет соответствовать синусоидальной функции.

Теперь у нас есть аналоговый сигнал, напряжение. Все еще не цифровой. Но мы знать, что это напряжение варьируется между (например) -1 В и + 1 В. Мы можем, из Конечно, присоедините вольтметр к проводам и считайте напряжение.

Произвольно, мы изменим шкалу на нашем вольтметре. Мы будем несколько вольт на 32767. Теперь он вызывает -1V -32767 и + 1V 32767 . Ах, и оно округляется до ближайшего целого числа.

Теперь мы подключаем наш вольтметр к компьютеру и даем команду компьютеру: прочитайте метр 44 100 раз в секунду. Добавьте второй вольтметр (для другой стереоканал), и теперь у нас есть данные, которые идут на аудио CD.

Этот формат называется стерео 44,100 Гц, 16-битный линейный PCM . И это действительно так просто куча измерений напряжения.

8 голосов
/ 09 апреля 2009

Аудио может быть представлено цифровыми образцами. По сути, сэмплер (также называемый аналого-цифровым преобразователем) захватывает значение аудиосигнала каждые 1 / фс, где фс - частота сэмплирования. АЦП затем квантует сигнал, который является операцией округления. Таким образом, если ваш сигнал колеблется от 0 до 3 Вольт (полный диапазон шкалы), то выборка будет округлена до, например, 16-разрядного числа. В этом примере 16-битное число записывается один раз каждые 1 / фс /

Так, например, большинство WAV / MP3 сэмплируют аудиосигнал с частотой 44 кГц. Я не знаю, сколько деталей вы хотите, но есть такая вещь, называемая «Частота дискретизации Найквиста», которая говорит, что частота дискретизации должна быть как минимум вдвое больше желаемой частоты. Таким образом, в вашем WAV / MP3-файле вы в лучшем случае сможете услышать частоту до 22 кГц.

В этой области вы можете углубиться в детали. Самой простой формой, безусловно, будет формат WAV. Это несжатый звук. Форматы, такие как mp3 и ogg, должны быть распакованы, прежде чем вы сможете работать с ними.

7 голосов

Пример генерации аудио минимального C

Пример ниже генерирует чистый синус 1000 кГц в необработанном формате. При обычной частоте дискретизации 44,1 кГц она будет длиться около 4 секунд.

main.c:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(void) {
    FILE *f;
    const double PI2 = 2 * acos(-1.0);
    const double SAMPLE_FREQ = 44100;
    const unsigned int NSAMPLES = 4 * SAMPLE_FREQ;
    uint16_t ampl;
    uint8_t bytes[2];
    unsigned int t;

    f = fopen("out.raw", "wb");
    for (t = 0; t < NSAMPLES; ++t) {
        ampl = UINT16_MAX * 0.5 * (1.0 + sin(PI2 * t * 1000.0 / SAMPLE_FREQ));
        bytes[0] = ampl >> 8;
        bytes[1] = ampl & 0xFF;
        fwrite(bytes, 2, sizeof(uint8_t), f);
    }
    fclose(f);
    return EXIT_SUCCESS;
}

GitHub upstream .

Генерировать out.raw:

gcc -std=c99 -o main main.c -lm
./main

Воспроизвести out.raw напрямую:

sudo apt-get install ffmpeg
ffplay -autoexit -f u16be -ar 44100 -ac 1 out.raw

или конвертируйте в более распространенный аудиоформат, а затем играйте с более распространенным аудиоплеером:

ffmpeg -f u16be -ar 44100 -ac 1 -i out.raw out.flac
vlc out.flac

Параметры поясняются по адресу: https://superuser.com/a/1063230/128124

Проверено на Ubuntu 18.04.

Canon in D in C

Вот более интересный пример синтеза.

Итог: https://www.youtube.com/watch?v=JISozfHATms

main.c

#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

typedef uint16_t point_type_t;

double PI2;

void write_ampl(FILE *f, point_type_t ampl) {
    uint8_t bytes[2];
    bytes[0] = ampl >> 8;
    bytes[1] = ampl & 0xFF;
    fwrite(bytes, 2, sizeof(uint8_t), f);
}

/* https://en.wikipedia.org/wiki/Piano_key_frequencies */
double piano_freq(unsigned int i) {
    return 440.0 * pow(2, (i - 49.0) / 12.0);
}

/* Chord formed by the nth note of the piano. */
point_type_t piano_sum(unsigned int max_ampl, unsigned int time,
        double sample_freq, unsigned int nargs, unsigned int *notes) {
    unsigned int i;
    double sum = 0;
    for (i = 0 ; i < nargs; ++i)
        sum += sin(PI2 * time * piano_freq(notes[i]) / sample_freq);
    return max_ampl * 0.5 * (nargs + sum) / nargs;
}

enum notes {
    A0 = 1, AS0, B0,
    C1, C1S, D1, D1S, E1, F1, F1S, G1, G1S, A1, A1S, B1,
    C2, C2S, D2, D2S, E2, F2, F2S, G2, G2S, A2, A2S, B2,
    C3, C3S, D3, D3S, E3, F3, F3S, G3, G3S, A3, A3S, B3,
    C4, C4S, D4, D4S, E4, F4, F4S, G4, G4S, A4, A4S, B4,
    C5, C5S, D5, D5S, E5, F5, F5S, G5, G5S, A5, A5S, B5,
    C6, C6S, D6, D6S, E6, F6, F6S, G6, G6S, A6, A6S, B6,
    C7, C7S, D7, D7S, E7, F7, F7S, G7, G7S, A7, A7S, B7,
    C8,
};

int main(void) {
    FILE *f;
    PI2 = 2 * acos(-1.0);
    const double SAMPLE_FREQ = 44100;
    point_type_t ampl;
    point_type_t max_ampl = UINT16_MAX;
    unsigned int t, i;
    unsigned int samples_per_unit = SAMPLE_FREQ * 0.375;
    unsigned int *ip[] = {
        (unsigned int[]){4, 2, C3, E4},
        (unsigned int[]){4, 2, G3, D4},
        (unsigned int[]){4, 2, A3, C4},
        (unsigned int[]){4, 2, E3, B3},

        (unsigned int[]){4, 2, F3, A3},
        (unsigned int[]){4, 2, C3, G3},
        (unsigned int[]){4, 2, F3, A3},
        (unsigned int[]){4, 2, G3, B3},

        (unsigned int[]){4, 3, C3, G4, E5},
        (unsigned int[]){4, 3, G3, B4, D5},
        (unsigned int[]){4, 2, A3,     C5},
        (unsigned int[]){4, 3, E3, G4, B4},

        (unsigned int[]){4, 3, F3, C4, A4},
        (unsigned int[]){4, 3, C3, G4, G4},
        (unsigned int[]){4, 3, F3, F4, A4},
        (unsigned int[]){4, 3, G3, D4, B4},

        (unsigned int[]){2, 3, C4, E4, C5},
        (unsigned int[]){2, 3, C4, E4, C5},
        (unsigned int[]){2, 3, G3, D4, D5},
        (unsigned int[]){2, 3, G3, D4, B4},

        (unsigned int[]){2, 3, A3, C4, C5},
        (unsigned int[]){2, 3, A3, C4, E5},
        (unsigned int[]){2, 2, E3,     G5},
        (unsigned int[]){2, 2, E3,     G4},

        (unsigned int[]){2, 3, F3, A3, A4},
        (unsigned int[]){2, 3, F3, A3, F4},
        (unsigned int[]){2, 3, C3,     E4},
        (unsigned int[]){2, 3, C3,     G4},

        (unsigned int[]){2, 3, F3, A3, F4},
        (unsigned int[]){2, 3, F3, A3, C5},
        (unsigned int[]){2, 3, G3, B3, B4},
        (unsigned int[]){2, 3, G3, B3, G4},

        (unsigned int[]){2, 3, C4, E4, C5},
        (unsigned int[]){1, 3, C4, E4, E5},
        (unsigned int[]){1, 3, C4, E4, G5},
        (unsigned int[]){1, 2, G3,     G5},
        (unsigned int[]){1, 2, G3,     A5},
        (unsigned int[]){1, 2, G3,     G5},
        (unsigned int[]){1, 2, G3,     F5},

        (unsigned int[]){3, 3, A3, C4, E5},
        (unsigned int[]){1, 3, A3, C4, E5},
        (unsigned int[]){1, 3, E3, G3, E5},
        (unsigned int[]){1, 3, E3, G3, F5},
        (unsigned int[]){1, 3, E3, G3, E5},
        (unsigned int[]){1, 3, E3, G3, D5},
    };
    f = fopen("canon.raw", "wb");
    for (i = 0; i < sizeof(ip) / sizeof(int*); ++i) {
        unsigned int *cur = ip[i];
        unsigned int total = samples_per_unit * cur[0];
        for (t = 0; t < total; ++t) {
            ampl = piano_sum(max_ampl, t, SAMPLE_FREQ, cur[1], &cur[2]);
            write_ampl(f, ampl);
        }
    }
    fclose(f);
    return EXIT_SUCCESS;
}

GitHub upstream .

Для YouTube я подготовил его как:

wget -O canon.png https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/The_C_Programming_Language_logo.svg/564px-The_C_Programming_Language_logo.svg.png
ffmpeg -loop 1 -y -i canon.png -i canon.flac -shortest -acodec copy -vcodec vp9 canon.mkv

как объяснено: https://superuser.com/questions/1041816/combine-one-image-one-audio-file-to-make-one-video-using-ffmpeg/1041818#1041818

Вот более физически ориентированный взгляд на генерацию звука: Как звук представлен числами?

Проверено на Ubuntu 18.04.

Физика

Аудио кодируется как одно число для каждого момента времени. Сравните это с видео, которое нуждается в числах WIDTH * HEIGHT в каждый момент времени.

Затем это число преобразуется в линейное смещение диафрагмы вашего динамика:

|   /
|  /
|-/
| | A   I   R
|-\
|  \
|   \
<-> displacement

|     /
|    /
|---/
|   | A I   R
|---\
|    \
|     \
<---> displacement

|       /
|      /
|-----/
|     | A I R
|-----\
|      \
|       \
<-----> displacement

Смещение выталкивает воздух назад и вперед, создавая перепады давления, которые проходят через воздух как P-волны .

Только смещение имеет значение: постоянный сигнал, даже максимальный, не производит звука: диафрагма просто остается в фиксированном положении.

Частота дискретизации определяет, как быстро должны выполняться смещения.

44,1 кГц - это обычная частота дискретизации, поскольку люди могут слышать до 20 кГц, и из-за теоремы Найквиста – Шеннона .

Частота дискретизации аналогична частоте кадров в секунду для видео, хотя она имеет гораздо более высокое значение по сравнению с диапазоном 25 (кинотеатр) - 144 (жесткие игровые мониторы), который мы обычно видим для видео.

Форматы

.raw - это недостаточно определенный формат, который содержит только байты амплитуды и не содержит метаданных.

Мы должны передать несколько параметров метаданных в командной строке, например, частоту дискретизации, поскольку формат не содержит эти данные.

Существуют также другие несжатые форматы, которые содержат все необходимые метаданные, например, .wav, см .: Синтез файлов WAV с нуля - C

На практике, однако, большинство людей имеют дело исключительно со сжатыми форматами, которые делают файлы / потоки намного меньше. Некоторые из этих форматов учитывают характеристики человеческого уха для дальнейшего сжатия звука с потерями.

Биология

Люди воспринимают звук главным образом по их частотному разложению (AKA Преобразование Фурье ).

Я думаю, это потому, что во внутреннем ухе есть части, которые резонируют с разными частотами (подтверждение TODO).

Поэтому при синтезировании музыки мы больше думаем о сложении частот, а не моментов времени. Это иллюстрируется в этом примере .

Это приводит к мысли в терминах одномерного вектора между 20 Гц и 20 кГц для каждого момента времени.

Математическое преобразование Фурье теряет понятие времени, поэтому при синтезе мы собираем группы точек, суммируем частоты для этой группы и принимаем там преобразование Фурье.

К счастью, преобразование Фурье является линейным, поэтому мы можем просто суммировать и нормализовать смещения напрямую.

Размер каждой группы точек приводит к компромиссу между точностью и временем, опосредованным той же математикой, что и Принцип неопределенности Гейзенберга .

Вейвлеты могут быть более точным математическим описанием этого промежуточного частотно-временного описания.

4 голосов
/ 09 апреля 2009

Простейшим способом представления звука в виде чисел является PCM (импульсная кодовая модуляция). Это означает, что амплитуда звука записывается с заданной частотой (каждое значение амплитуды называется сэмплом). Качество звука CD, например, составляет 16 битных сэмплов (в стерео) на частоте 44100 Гц.

Сэмпл может быть представлен как целое число (обычно 8, 12, 16, 24 или 32 бита) или число с плавающей запятой (16-битное с плавающей точкой или 32-битное двойное). Номер может быть подписан или не подписан.

Для 16-битных сэмплов со значением значение 0 будет посередине, а -32768 и 32767 будут максимальными амплитудами. Для 16-битных выборок без знака значение 32768 будет посередине, а 0 и 65535 будут максимальными амплитудами.

Для выборок с плавающей запятой обычным форматом является то, что 0 находится посередине, а -1,0 и 1,0 - максимальные амплитуды.

Затем данные PCM можно сжать, например, с помощью MP3.

3 голосов
/ 09 апреля 2009

Я думаю, что выборки формы волны на определенной частоте выборки были бы самым основным представлением.

2 голосов
/ 09 апреля 2009

Я думаю, что хорошим способом начать воспроизведение со звуком было бы Обработка и Минимум . Эта программа будет рисовать частотный спектр звука с вашего микрофона!

import ddf.minim.*;
import ddf.minim.analysis.*;

AudioInput in;
FFT fft;

void setup()
{
  size(1024, 600);
  noSmooth();
  Minim.start(this);
  in = Minim.getLineIn();
  fft = new FFT(in.bufferSize(), in.sampleRate());
}

void draw()
{
  background(0);
  fft.forward(in.mix);
  stroke(255);
  for(int i = 0; i < fft.specSize(); i++)
    line(i*2+1, height, i*2+1, height - fft.getBand(i)*10);
}

void stop()
{
  in.close();
  Minim.stop();
  super.stop();
}
2 голосов
/ 09 апреля 2009

Посмотрите на такие вещи, как аналого-цифровое преобразование. Это должно начать вас. Эти устройства могут преобразовывать звуковой сигнал (синусоиды) в цифровые представления. Итак, 16-разрядный АЦП мог бы представлять синус от -32768 до 32768. Это с фиксированной запятой. Это также возможно сделать с плавающей запятой (хотя это не рекомендуется из соображений производительности, но может быть необходимо из соображений диапазона). Обратное (цифроаналоговое преобразование) происходит, когда мы конвертируем числа в синусоидальные волны. Это обрабатывается чем-то, что называется ЦАП.

2 голосов
/ 09 апреля 2009

Вы когда-нибудь смотрели на форму волны крупным планом? Ось Y просто представлена ​​как целое число, обычно в 16 битах.

1 голос
/ 16 сентября 2016

Преобразование фактического аналогового звука в цифровую форму выполняется в 2 этапа.

  1. Sampling
  2. Квантование

Sampling

Скорость дискретизации непрерывного сигнала (в данном случае аудио) называется частотой дискретизации. Частотный диапазон, воспринимаемый людьми, составляет 20 - 20000 Гц. Однако на компакт-дисках используется теорема выборки Найквиста, которая означает частоту дискретизации 44 100 Гц и охватывает частоты в диапазоне 0–22 050 Гц.

Квантование

Дискретный набор значений, полученных на этапе «Выборка», теперь необходимо преобразовать в конечное число значений. 8-битное квантование обеспечивает 256 возможных значений, в то время как 16-битное квантование обеспечивает до 65 536 значений.

0 голосов
/ 25 ноября 2016

Все ответы относятся к частоте выборки, но не касаются вопроса. Я полагаю, что конкретный снимок звука будет включать отдельные амплитуды для множества различных частот (скажем, вы одновременно нажимаете и А, и С на клавиатуре, причем А громче). Как это записывается в 16-битном числе? Если все, что вы делаете, это измеряете амплитуду (насколько громкий звук), как вы получаете разные ноты?

Ах! Мне кажется, я понял это из этого комментария: «Затем это число преобразуется в линейное смещение диафрагмы вашего динамика». Примечания появляются по тому, как быстро вибрирует диафрагма. Вот почему вам нужно 44000 различных значений в секунду. Нота где-то порядка 1000 герц, поэтому чистая нота заставляет диафрагму входить и выходить примерно 1000 раз в секунду. Запись всего оркестра имеет много разных нот повсюду, и это чудесным образом может быть преобразовано в единую историю движения диафрагмы. 44 000 раз в секунду диафрагме дают указание немного входить или выходить, и этот простой (длинный) список чисел может представлять Бейонсе и Бетховена!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...