Заблокирован
1

Работа с Wav файлом

09.07.2014, 11:57. Показов 9837. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Пишу курсовую. Надо получить спект Wav файла. Прочитал достаточно статей и форумов. В общем оформил шапку и вытащил параметры.

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

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

нашел вот это (0x00,0x01),(0x22,0x43),(0x74,0x15),(0x74,0x65)... - 16 бит моно

что касается самого wav файла, работаю с 44100Гц 1 канал 2 байта

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <fstream>
#include <iostream>
using namespace std;
struct WAVHEADER
{
char chunkId[4];// RIFF-заголовок:
unsigned long chunkSize;
char format[4]; // Содержит символы "WAVE"
char subchunk1Id[4];// Содержит символы "fmt "
unsigned long subchunk1Size; // Это оставшийся размер подцепочки, начиная с этой позиции.
unsigned short audioFormat;// Значения, отличающиеся от 1, обозначают некоторый формат сжатия.
unsigned short numChannels;// Количество каналов. Моно = 1, Стерео = 2 и т.д.
unsigned long sampleRate;// Частота дискретизации. 8000 Гц, 44100 Гц и т.д
unsigned long byteRate;// sampleRate * numChannels * bitsPerSample/8
unsigned short blockAlign; // numChannels * bitsPerSample/8  Количество байт для одного сэмпла, включая все каналы.
unsigned short bitsPerSample; // Так называемая "глубиная" или точность звучания. 8 бит, 16 бит и т.д.
char subchunk2Id[4]; // Содержит символы "data"
unsigned long subchunk2Size; //numSamples * numChannels * bitsPerSample/8 Количество байт в области данных.
};
void main(){
    FILE *file;
    errno_t err;
    err = fopen_s(&file, "00032.00.wav", "rb");
    if (err)
    {
    printf_s("Failed open file, error %d", err);
    system("pause");
    exit(0);
    }
    WAVHEADER head;
    fread_s(&head, sizeof(WAVHEADER), sizeof(WAVHEADER), 1, file);
    
    float fDurationSeconds = 1.f * head.subchunk2Size / (head.bitsPerSample / 8) / head.numChannels / head.sampleRate;
    int iDurationMinutes = (int)floor(fDurationSeconds) / 60;
    fDurationSeconds = fDurationSeconds - (iDurationMinutes * 60);
    printf_s("Duration: %02d:%02.f\n", iDurationMinutes, fDurationSeconds);
 
    printf_s("Sample rate: %d\n", head.sampleRate);
    printf_s("Channels: %d\n", head.numChannels);
    printf_s("Byte per sample: %d\n", head.bitsPerSample/8);
    /*printf_s("Byte Rate: %d\n", head.byteRate);
    printf_s("Block Align: %d\n", head.blockAlign);
    printf_s("Subchunk 2 Size: %d\n", head.subchunk2Size);*/
    system("pause");
 
???????????????????
 
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.07.2014, 11:57
Ответы с готовыми решениями:

Работа с wav-файлами в C++ с использованием PlaySound()
Пытаюсь написать программу для генерирования звуковых сигналов различных частот и амплитуд на...

Чтение и работа с данными из файла WAV
Передо мной стоит задача встроить скрытую информацию в WAV файл, с помощью определенных методов...

Написать программу, формирующую по исходному WAV файлу новый WAV файл
Написать программу, формирующую по исходному WAV файлу новый WAV файл, со сглаженным вершинами...

Работа с wav файлом!
Прошу помочь!!! Проблема состоит в том что нужно открыть wav файл, взять дынные с него и построить...

18
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
09.07.2014, 13:45 2
Myha_fly, так у вас все известно:
Количество байт в области данных и bitsPerSample.
Количество байт на все данные вы знаете, сколько бит на "одну единицу данных" (сэмпл) тоже знаете. Выбираете нужный тип данных и читаете. Все.

Добавлено через 17 секунд
Ну и число каналов тоже знаете.
0
Заблокирован
09.07.2014, 14:43  [ТС] 3
HighPredator, может это я и получил, но мне это ничего не дало
я не понимаю как мне вытащить данные из файла, в стиле просто добавить в шапку массив и просто считывать? (так же если это так, я не понимаю какого он размера должен быть (единственное предположение "numSamples * numChannels * bitsPerSample/8"))
так же меня смущает 16ичные переменные и то что они идут парами "(0x00,0x01),(0x22,0x43),(0x74,0x15)"
0
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
09.07.2014, 15:02 4
Цитата Сообщение от Myha_fly Посмотреть сообщение
может это я и получил, но мне это ничего не дало
Очень плохо. плохо читаете.
Цитата Сообщение от Myha_fly Посмотреть сообщение
какого он размера должен быть (единственное предположение "numSamples * numChannels * bitsPerSample/8")
Вот это число байт на весь массив. Чувствуете, да? Вам нужно только определить сколько в нем отсчетов вашего сигнала. Это вы будете знать из числа байт на отсчет. То есть из получаемого вами числа бит на отсчет, т.е. на единицу данных. Дальше арифметика. Учтите число каналов.
Цитата Сообщение от Myha_fly Посмотреть сообщение
в стиле просто добавить в шапку массив и просто считывать?
Это уже ваше дело как. Как говорится: кто как.
0
Почетный модератор
Эксперт С++
5850 / 2861 / 392
Регистрация: 01.11.2011
Сообщений: 6,907
09.07.2014, 15:58 5
Цитата Сообщение от Myha_fly Посмотреть сообщение
Но я не понимаю, как узнать сколько их и какой размерности. То есть, нужно ли создавать для них массив и какой размерности. В каком формате данные. и в каком их лучше всего отправить на обработку
Волшебные картинки спешат на помощь:
Работа с Wav файлом


Общее число требуемых для создания массивов, по одному на каждый канал, равняется NumChannels. Соответственно для моноканала потребуется создать только один массив, для стереоканала - два, и так далее.
Subchunk2Size это общий размер всех-всех данных. Соответственно поделив это число на количество каналов узнаем сколько элементов должен содержать массив. Умножив это количество на размер одного элемента (BitPerSample) получим требуемый размер памяти под массив.

Сразу после шапки, каждый блок данных (размером BlockAlign) содержит строго по очереди одинаковые элементы каждого канала - то есть в первом блоке будет расположен первый элемент (chunk) первого канала, затем первый элемент второго канала. Во втором блоке данных - сначала второй элемент первого канала, затем второй элемент второго канала. И так далее. Для четырехканальной записи, каждый блок будет содержать ровно четыре значения. Для моноканала, соответственно, каждый блок данных будет размером с один элемент канала, то есть равен выбранной глубине звука.

P.S. Что-то я совсем забыл: BitPerSample нужно делить на 8, чтобы привести все к одной единице измерений. Собственно к байтам.
1
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
10.07.2014, 08:37 6
Ну и вот еще: https://www.cyberforum.ru/cpp-... ost5946601
0
Заблокирован
10.07.2014, 11:34  [ТС] 7
В правильном направлении я двигаюсь?
Если да, то как считать инфу с буфера?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <fstream>
#include <iostream>
using namespace std;
 
struct WAVHEADER
{
char chunkId[4];// RIFF-заголовок:
unsigned long chunkSize;
char format[4]; // Содержит символы "WAVE"
char subchunk1Id[4];// Содержит символы "fmt "
unsigned long subchunk1Size; // Это оставшийся размер подцепочки, начиная с этой позиции.
unsigned short audioFormat;// Значения, отличающиеся от 1, обозначают некоторый формат сжатия.
unsigned short numChannels;// Количество каналов. Моно = 1, Стерео = 2 и т.д.
unsigned long sampleRate;// Частота дискретизации. 8000 Гц, 44100 Гц и т.д
unsigned long byteRate;// sampleRate * numChannels * bitsPerSample/8
unsigned short blockAlign; // numChannels * bitsPerSample/8 Количество байт для одного сэмпла, включая все каналы.
unsigned short bitsPerSample; // Так называемая "глубиная" или точность звучания. 8 бит, 16 бит и т.д.
char subchunk2Id[4]; // Содержит символы "data"
unsigned long subchunk2Size; //numSamples * numChannels * bitsPerSample/8 Количество байт в области данных.
short *data;
 
};
 
void main(){
 FILE *file;
 errno_t err;
 err = fopen_s(&file, "00032.00.wav", "rb");
 if (err)
 {
 printf_s("Failed open file, error %d", err);
 system("pause");
 exit(0);
 }
 
 WAVHEADER head;
 
 fread_s(&head, sizeof(WAVHEADER), sizeof(WAVHEADER), 1, file);
 
 float fDurationSeconds = 1.f * head.subchunk2Size / (head.bitsPerSample / 8) / head.numChannels / head.sampleRate;
 int iDurationMinutes = (int)floor(fDurationSeconds) / 60;
 fDurationSeconds = fDurationSeconds - (iDurationMinutes * 60);
 
 printf_s("Duration: %02d:%02.f\n", iDurationMinutes, fDurationSeconds);
 printf_s("Sample rate: %d\n", head.sampleRate);
 printf_s("Channels: %d\n", head.numChannels);
 printf_s("Byte per sample: %d\n", head.bitsPerSample/8);
 
 ifstream fil;
 char *str;
 fil.open("00032.00.wav",ios::beg|ios::in|ios::binary);
 fil.read((char*)&head,44);
 
 head.data=new short[head.subchunk2Size]; //Создаём буфер, для хранения звука
 
 fil.read((char*)head.data,head.subchunk2Size);
    for(int i=0;i<head.subchunk2Size;i++){
        cout<<head.data[i]<<" ";
    }
 
 fil.close();
 system("pause");
}
Добавлено через 13 минут
Не правильно вопрос задал) в правильном направлении я двигаюсь? В плане размерностей и форматов, не хотелось бы с неверными данными работать
А как по буферу пробежаться в принципе понимаю)
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
10.07.2014, 22:25 8
за блоком fmt могут идти другие, а не сразу data
0
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
11.07.2014, 09:41 9
Цитата Сообщение от Myha_fly Посмотреть сообщение
в правильном направлении я двигаюсь?
Короче говоря, если вы железно будете работать только с каноническим форматом wave, то примерно в правильном (разберетесь со временем), если вы решаете хоть насколько-то общую задачу, то лучше вообще использовать готовые библиотеки. Т.к. как сказал Croessmah при audioFormat != 1
Цитата Сообщение от Croessmah Посмотреть сообщение
за блоком fmt могут идти другие, а не сразу data
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
11.07.2014, 11:35 10
Цитата Сообщение от HighPredator Посмотреть сообщение
Т.к. как сказал Croessmah при audioFormat != 1
и в не сжатых PCM могут идти дополнительные блоки. Когда писали код, по ссылке из поста #6, столкнулись с целой телегой таких файлов, в результате чего получали искаженные данные по непонятным нам причинам. Расковыряв аудио файл в HEX-редакторе всё стало понятно. В код был добавлен код для считывания не только fmt и data, а любых блоков.
0
SatanaXIII
11.07.2014, 11:59
  #11

Не по теме:

Цитата Сообщение от Croessmah Посмотреть сообщение
в результате чего получали искаженные данные по непонятным нам причинам. Расковыряв аудио файл в HEX-редакторе всё стало понятно. В код был добавлен код для считывания не только fmt и data, а любых блоков.
Значит не я один такой. *смахивает скупую слезу*

0
HighPredator
11.07.2014, 12:31
  #12

Не по теме:

Цитата Сообщение от Croessmah Посмотреть сообщение
и в не сжатых PCM могут идти дополнительные блоки
Это не соответствует спецификации канонического формата wave. Честно, я не встречал файлов, у которых есть доп. блоки и при этом формат = 1. Это вроде как нарушение постулата однозначности определения формата по идентификатору. Но хотя сейчас такое время...

0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
11.07.2014, 20:00 13
Цитата Сообщение от HighPredator Посмотреть сообщение
Честно, я не встречал файлов, у которых есть доп. блоки и при этом формат = 1.
8bit.wav.zip
А Compression Code = 1 показывает что данные не сжаты, но никто не мешает мне добавить блок с именем автора
Это вроде как нарушение постулата однозначности определения формата по идентификатору.
В приведенном файле имеется блок fact, который необходим для сжатых файлов, но может присутствовать и не в сжатых, это никто не ограничивает.
0
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 12
25.03.2015, 12:43 14
Ребята, столкнулся с такой проблемой, при audioFormat != 1 поле subchunk2Size содержит в разы большее значение, чем размер файла. Для audioFormat == 1 все соответствует.
В описании формата wav поле subchunk2Size обозначено как "Количество байт в области данных". Т.е. это получается, если wav раскодировать, то количество данных будет соответствовать subchunk2Size, а не filesize - 44?
0
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
25.03.2015, 13:47 15
Рак, можно конкретику? Сами значения и файл, если возможно.
0
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 12
25.03.2015, 14:31 16
HighPredator, конкретика такая:
У меня windows xp, файл:
C:\Windows\Media\Windows XP - восклицание.wav - размер файла 42576Б, кодировка PCM, поле subchunk2Size - 42532 (т.е. 42576 - 44),
C:\Windows\Media\Windows XP - восстановление.wav - размер файла 19458Б, кодировка PCM, поле subchunk2Size - 19414

C:\Program Files\Messanger\newalert.wav - 9306Б, кодировка Microsoft ADPCM, поле subchunk2Size - 16777223
C:\Program Files\Messanger\newemail.wav - 18058Б, кодировка Microsoft ADPCM, поле subchunk2Size - 16777223
C:\Program Files\Microsoft Office\Office14\REMINDER.wav - 108800Б, кодировка Microsoft ADPCM, поле subchunk2Size - 16777223

Вот еще, у Microsoft ADPCM поле subchunk2Id не "data", а белиберда какая-то.
0
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
25.03.2015, 17:16 17
Судя по тому, что у вас значения чанков для тех двух файлов совпадают, да еще и сами по себе черти-какие, то скорее всего имеет место ошибка считывания.
Цитата Сообщение от Рак Посмотреть сообщение
у Microsoft ADPCM поле subchunk2Id не "data", а белиберда какая-то
Сейчас открыл фаром файл
Цитата Сообщение от Рак Посмотреть сообщение
C:\Program Files\Microsoft Office\Office14\REMINDER.wav
Блок data вроде на месте и выглядит как надо.
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
25.03.2015, 17:45 18
Вот еще, у Microsoft ADPCM поле subchunk2Id не "data", а белиберда какая-то.
Значит где-то при считывании накосячили. Как вариант могу предположить, что после блока "fmt " идут дополнительные байты (Extra Format Bytes), про которые забыли.
1
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 12
25.03.2015, 18:30 19
Цитата Сообщение от Croessmah Посмотреть сообщение
Значит где-то при считывании накосячили. Как вариант могу предположить, что после блока "fmt " идут дополнительные байты (Extra Format Bytes), про которые забыли.
Скажу больше, даже и не знал, спасибо.
Действительно, после поля bitsPerSample для audioFormat != 1 следующие 2 байта размер Extra области и данные, а дальше, как положено, "data".
0
25.03.2015, 18:30
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.03.2015, 18:30
Помогаю со студенческими работами здесь

Работа с WAV-файлом
Народ, помогите пожалуйста. Необходимо написать обработчик сигнала который будет демодулировать,...

GUI Работа с текстовым файлом, лог файлом не мешая системе
Хочу написать прогу которая будет по таймеру искать в тхт - лог файле сообщение об ошибке. Например...

Работа с wav файлами
Здравствуйте, у меня такая задача: имеется рабочий код для с++ и мне необходимо перегнать его под...

Работа с файлом (корректный код, некорректная работа программы)
Для записи и чтения файла использую разные функции. По одиночке они работают нормально. Вставляю...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru