Форум программистов, компьютерный форум, киберфорум
Наши страницы

C++

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

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

09.07.2014, 11:57. Просмотров 3080. Ответов 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++):

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

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

Деление Wav-файла на два канала - C++
Реализовать функцию разделяющую входной wav файл на каналы (на два выходных файла) с возможностью уменьшения амплитуд любого из каналов. ...

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

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

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

18
HighPredator
5544 / 1857 / 346
Регистрация: 10.12.2010
Сообщений: 5,479
Записей в блоге: 2
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
5544 / 1857 / 346
Регистрация: 10.12.2010
Сообщений: 5,479
Записей в блоге: 2
09.07.2014, 15:02 #4
Цитата Сообщение от Myha_fly Посмотреть сообщение
может это я и получил, но мне это ничего не дало
Очень плохо. плохо читаете.
Цитата Сообщение от Myha_fly Посмотреть сообщение
какого он размера должен быть (единственное предположение "numSamples * numChannels * bitsPerSample/8")
Вот это число байт на весь массив. Чувствуете, да? Вам нужно только определить сколько в нем отсчетов вашего сигнала. Это вы будете знать из числа байт на отсчет. То есть из получаемого вами числа бит на отсчет, т.е. на единицу данных. Дальше арифметика. Учтите число каналов.
Цитата Сообщение от Myha_fly Посмотреть сообщение
в стиле просто добавить в шапку массив и просто считывать?
Это уже ваше дело как. Как говорится: кто как.
0
SatanaXIII
Супер-модератор
Эксперт С++
5619 / 2654 / 247
Регистрация: 01.11.2011
Сообщений: 6,553
Завершенные тесты: 1
09.07.2014, 15:58 #5
Цитата Сообщение от Myha_fly Посмотреть сообщение
Но я не понимаю, как узнать сколько их и какой размерности. То есть, нужно ли создавать для них массив и какой размерности. В каком формате данные. и в каком их лучше всего отправить на обработку
Волшебные картинки спешат на помощь:
Работа с Wav файлом

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

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

P.S. Что-то я совсем забыл: BitPerSample нужно делить на 8, чтобы привести все к одной единице измерений. Собственно к байтам.
1
Croessmah
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 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
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
10.07.2014, 22:25 #8
за блоком fmt могут идти другие, а не сразу data
0
HighPredator
5544 / 1857 / 346
Регистрация: 10.12.2010
Сообщений: 5,479
Записей в блоге: 2
11.07.2014, 09:41 #9
Цитата Сообщение от Myha_fly Посмотреть сообщение
в правильном направлении я двигаюсь?
Короче говоря, если вы железно будете работать только с каноническим форматом wave, то примерно в правильном (разберетесь со временем), если вы решаете хоть насколько-то общую задачу, то лучше вообще использовать готовые библиотеки. Т.к. как сказал Croessmah при audioFormat != 1
Цитата Сообщение от Croessmah Посмотреть сообщение
за блоком fmt могут идти другие, а не сразу data
0
Croessmah
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 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
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 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
5544 / 1857 / 346
Регистрация: 10.12.2010
Сообщений: 5,479
Записей в блоге: 2
25.03.2015, 13:47 #15
Рак, можно конкретику? Сами значения и файл, если возможно.
0
25.03.2015, 13:47
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.03.2015, 13:47
Привет! Вот еще темы с ответами:

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

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

Как из Wav файла получить комплексные значения для быстрого преобразования Фурье? - C++
Пишу программу для вывода спектра Wav файла Беру данные из Wav файла, прочел шапку, дошел до самих значений. Как понимаю это амплитудные...

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


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

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

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