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

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

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

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

Скрыть rar в wav
В общем надо програму которая может скрыть rar в wav а потом так же извлечь...

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

Деление Wav-файла на два канала
Реализовать функцию разделяющую входной wav файл на каналы (на два выходных...

Наложение звукового эффекта на wav файл
Надо на звуковой файл в формате waw, наложить звуковой эффект, может кто...

Перенести код считывания wav-файла на Delphi.
Вот сам код: typedef struct { char id_riff; long len_riff; ...

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

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

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

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

P.S. Что-то я совсем забыл: BitPerSample нужно делить на 8, чтобы привести все к одной единице измерений. Собственно к байтам.
1
Croessmah
++Ͻ
14158 / 8083 / 1513
Регистрация: 27.09.2012
Сообщений: 19,921
Записей в блоге: 3
Завершенные тесты: 1
10.07.2014, 08:37 #6
Ну и вот еще: http://www.cyberforum.ru/cpp-beginners/thread1128821.html#post5946601
0
Myha_fly
Заблокирован
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
Croessmah
++Ͻ
14158 / 8083 / 1513
Регистрация: 27.09.2012
Сообщений: 19,921
Записей в блоге: 3
Завершенные тесты: 1
10.07.2014, 22:25 #8
за блоком fmt могут идти другие, а не сразу data
0
HighPredator
5647 / 1964 / 716
Регистрация: 10.12.2010
Сообщений: 5,690
Записей в блоге: 3
11.07.2014, 09:41 #9
Цитата Сообщение от Myha_fly Посмотреть сообщение
в правильном направлении я двигаюсь?
Короче говоря, если вы железно будете работать только с каноническим форматом wave, то примерно в правильном (разберетесь со временем), если вы решаете хоть насколько-то общую задачу, то лучше вообще использовать готовые библиотеки. Т.к. как сказал Croessmah при audioFormat != 1
Цитата Сообщение от Croessmah Посмотреть сообщение
за блоком fmt могут идти другие, а не сразу data
0
Croessmah
++Ͻ
14158 / 8083 / 1513
Регистрация: 27.09.2012
Сообщений: 19,921
Записей в блоге: 3
Завершенные тесты: 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
Croessmah
++Ͻ
14158 / 8083 / 1513
Регистрация: 27.09.2012
Сообщений: 19,921
Записей в блоге: 3
Завершенные тесты: 1
11.07.2014, 20:00 #13
Цитата Сообщение от HighPredator Посмотреть сообщение
Честно, я не встречал файлов, у которых есть доп. блоки и при этом формат = 1.
8bit.wav.zip
А Compression Code = 1 показывает что данные не сжаты, но никто не мешает мне добавить блок с именем автора
Это вроде как нарушение постулата однозначности определения формата по идентификатору.
В приведенном файле имеется блок fact, который необходим для сжатых файлов, но может присутствовать и не в сжатых, это никто не ограничивает.
0
Рак
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 11
25.03.2015, 12:43 #14
Ребята, столкнулся с такой проблемой, при audioFormat != 1 поле subchunk2Size содержит в разы большее значение, чем размер файла. Для audioFormat == 1 все соответствует.
В описании формата wav поле subchunk2Size обозначено как "Количество байт в области данных". Т.е. это получается, если wav раскодировать, то количество данных будет соответствовать subchunk2Size, а не filesize - 44?
0
HighPredator
5647 / 1964 / 716
Регистрация: 10.12.2010
Сообщений: 5,690
Записей в блоге: 3
25.03.2015, 13:47 #15
Рак, можно конкретику? Сами значения и файл, если возможно.
0
Рак
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 11
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
HighPredator
5647 / 1964 / 716
Регистрация: 10.12.2010
Сообщений: 5,690
Записей в блоге: 3
25.03.2015, 17:16 #17
Судя по тому, что у вас значения чанков для тех двух файлов совпадают, да еще и сами по себе черти-какие, то скорее всего имеет место ошибка считывания.
Цитата Сообщение от Рак Посмотреть сообщение
у Microsoft ADPCM поле subchunk2Id не "data", а белиберда какая-то
Сейчас открыл фаром файл
Цитата Сообщение от Рак Посмотреть сообщение
C:\Program Files\Microsoft Office\Office14\REMINDER.wav
Блок data вроде на месте и выглядит как надо.
0
Croessmah
++Ͻ
14158 / 8083 / 1513
Регистрация: 27.09.2012
Сообщений: 19,921
Записей в блоге: 3
Завершенные тесты: 1
25.03.2015, 17:45 #18
Вот еще, у Microsoft ADPCM поле subchunk2Id не "data", а белиберда какая-то.
Значит где-то при считывании накосячили. Как вариант могу предположить, что после блока "fmt " идут дополнительные байты (Extra Format Bytes), про которые забыли.
1
Рак
1 / 1 / 0
Регистрация: 06.02.2013
Сообщений: 11
25.03.2015, 18:30 #19
Цитата Сообщение от Croessmah Посмотреть сообщение
Значит где-то при считывании накосячили. Как вариант могу предположить, что после блока "fmt " идут дополнительные байты (Extra Format Bytes), про которые забыли.
Скажу больше, даже и не знал, спасибо.
Действительно, после поля bitsPerSample для audioFormat != 1 следующие 2 байта размер Extra области и данные, а дальше, как положено, "data".
0
25.03.2015, 18:30
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.03.2015, 18:30
Привет! Вот еще темы с решениями:

Как написать простой конвертер из wav в mp3
Здравствуйте! Ребят, я в С++ прохо эрудирован, но мне нужено написать...

Читать данных wav файла и нарисовать его частотный спектр в C++
Помогите мне для получить данных wav файла и нарисовать его частотный спектр в...

Как из wav файла получить читаемый txt, а потом обратно
Извиняюсь если не совсем по адресу, но я уверен что местные читатели знают как...

Написать функцию вычисляющую амплитудный спектр отсчетов звукового сигнала формата WAV
Нужно написать функцию вычисляющую амплитудный спектр отсчетов звукового...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru