Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.58
Myha_fly
Заблокирован
#1

Работа с Wav файлом - C++

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

Пишу курсовую. Надо получить спект 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");
 
???????????????????
 
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.07.2014, 11:57     Работа с Wav файлом
Посмотрите здесь:

Работа с файлом C++
C++ Работа с файлом
работа с файлом C++
C++ c++ работа с файлом
C++ C++. Работа с файлом
Работа с файлом C++
Работа с файлом C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
HighPredator
5454 / 1820 / 335
Регистрация: 10.12.2010
Сообщений: 5,381
Записей в блоге: 3
09.07.2014, 13:45     Работа с Wav файлом #2
Myha_fly, так у вас все известно:
Количество байт в области данных и bitsPerSample.
Количество байт на все данные вы знаете, сколько бит на "одну единицу данных" (сэмпл) тоже знаете. Выбираете нужный тип данных и читаете. Все.

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

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

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

P.S. Что-то я совсем забыл: BitPerSample нужно делить на 8, чтобы привести все к одной единице измерений. Собственно к байтам.
Croessmah
Модератор
Эксперт CЭксперт С++
12878 / 7264 / 810
Регистрация: 27.09.2012
Сообщений: 17,944
Записей в блоге: 2
Завершенные тесты: 1
10.07.2014, 08:37     Работа с Wav файлом #6
Ну и вот еще: http://www.cyberforum.ru/cpp-beginne...ml#post5946601
Myha_fly
Заблокирован
10.07.2014, 11:34  [ТС]     Работа с Wav файлом #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 минут
Не правильно вопрос задал) в правильном направлении я двигаюсь? В плане размерностей и форматов, не хотелось бы с неверными данными работать
А как по буферу пробежаться в принципе понимаю)
Croessmah
Модератор
Эксперт CЭксперт С++
12878 / 7264 / 810
Регистрация: 27.09.2012
Сообщений: 17,944
Записей в блоге: 2
Завершенные тесты: 1
10.07.2014, 22:25     Работа с Wav файлом #8
за блоком fmt могут идти другие, а не сразу data
HighPredator
5454 / 1820 / 335
Регистрация: 10.12.2010
Сообщений: 5,381
Записей в блоге: 3
11.07.2014, 09:41     Работа с Wav файлом #9
Цитата Сообщение от Myha_fly Посмотреть сообщение
в правильном направлении я двигаюсь?
Короче говоря, если вы железно будете работать только с каноническим форматом wave, то примерно в правильном (разберетесь со временем), если вы решаете хоть насколько-то общую задачу, то лучше вообще использовать готовые библиотеки. Т.к. как сказал Croessmah при audioFormat != 1
Цитата Сообщение от Croessmah Посмотреть сообщение
за блоком fmt могут идти другие, а не сразу data
Croessmah
Модератор
Эксперт CЭксперт С++
12878 / 7264 / 810
Регистрация: 27.09.2012
Сообщений: 17,944
Записей в блоге: 2
Завершенные тесты: 1
11.07.2014, 11:35     Работа с Wav файлом #10
Цитата Сообщение от HighPredator Посмотреть сообщение
Т.к. как сказал Croessmah при audioFormat != 1
и в не сжатых PCM могут идти дополнительные блоки. Когда писали код, по ссылке из поста #6, столкнулись с целой телегой таких файлов, в результате чего получали искаженные данные по непонятным нам причинам. Расковыряв аудио файл в HEX-редакторе всё стало понятно. В код был добавлен код для считывания не только fmt и data, а любых блоков.
SatanaXIII
11.07.2014, 11:59
  #11

Не по теме:

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

HighPredator
11.07.2014, 12:31
  #12

Не по теме:

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

Croessmah
Модератор
Эксперт CЭксперт С++
12878 / 7264 / 810
Регистрация: 27.09.2012
Сообщений: 17,944
Записей в блоге: 2
Завершенные тесты: 1
11.07.2014, 20:00     Работа с Wav файлом #13
Цитата Сообщение от HighPredator Посмотреть сообщение
Честно, я не встречал файлов, у которых есть доп. блоки и при этом формат = 1.
8bit.wav.zip
А Compression Code = 1 показывает что данные не сжаты, но никто не мешает мне добавить блок с именем автора
Это вроде как нарушение постулата однозначности определения формата по идентификатору.
В приведенном файле имеется блок fact, который необходим для сжатых файлов, но может присутствовать и не в сжатых, это никто не ограничивает.
Рак
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 11
25.03.2015, 12:43     Работа с Wav файлом #14
Ребята, столкнулся с такой проблемой, при audioFormat != 1 поле subchunk2Size содержит в разы большее значение, чем размер файла. Для audioFormat == 1 все соответствует.
В описании формата wav поле subchunk2Size обозначено как "Количество байт в области данных". Т.е. это получается, если wav раскодировать, то количество данных будет соответствовать subchunk2Size, а не filesize - 44?
HighPredator
5454 / 1820 / 335
Регистрация: 10.12.2010
Сообщений: 5,381
Записей в блоге: 3
25.03.2015, 13:47     Работа с Wav файлом #15
Рак, можно конкретику? Сами значения и файл, если возможно.
Рак
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 11
25.03.2015, 14:31     Работа с Wav файлом #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", а белиберда какая-то.
HighPredator
5454 / 1820 / 335
Регистрация: 10.12.2010
Сообщений: 5,381
Записей в блоге: 3
25.03.2015, 17:16     Работа с Wav файлом #17
Судя по тому, что у вас значения чанков для тех двух файлов совпадают, да еще и сами по себе черти-какие, то скорее всего имеет место ошибка считывания.
Цитата Сообщение от Рак Посмотреть сообщение
у Microsoft ADPCM поле subchunk2Id не "data", а белиберда какая-то
Сейчас открыл фаром файл
Цитата Сообщение от Рак Посмотреть сообщение
C:\Program Files\Microsoft Office\Office14\REMINDER.wav
Блок data вроде на месте и выглядит как надо.
Croessmah
Модератор
Эксперт CЭксперт С++
12878 / 7264 / 810
Регистрация: 27.09.2012
Сообщений: 17,944
Записей в блоге: 2
Завершенные тесты: 1
25.03.2015, 17:45     Работа с Wav файлом #18
Вот еще, у Microsoft ADPCM поле subchunk2Id не "data", а белиберда какая-то.
Значит где-то при считывании накосячили. Как вариант могу предположить, что после блока "fmt " идут дополнительные байты (Extra Format Bytes), про которые забыли.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.03.2015, 18:30     Работа с Wav файлом
Еще ссылки по теме:

Работа с файлом C++
Работа с файлом C++
C++ Работа с файлом
C++ работа с файлом
Написать программу, формирующую по исходному WAV файлу новый WAV файл C++

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

Или воспользуйтесь поиском по форуму:
Рак
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 11
25.03.2015, 18:30     Работа с Wav файлом #19
Цитата Сообщение от Croessmah Посмотреть сообщение
Значит где-то при считывании накосячили. Как вариант могу предположить, что после блока "fmt " идут дополнительные байты (Extra Format Bytes), про которые забыли.
Скажу больше, даже и не знал, спасибо.
Действительно, после поля bitsPerSample для audioFormat != 1 следующие 2 байта размер Extra области и данные, а дальше, как положено, "data".
Yandex
Объявления
25.03.2015, 18:30     Работа с Wav файлом
Ответ Создать тему
Опции темы

Текущее время: 17:02. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru