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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Sonance
6 / 6 / 3
Регистрация: 15.02.2013
Сообщений: 55
#1

Побитная запись в контейнер wav - C++

24.02.2014, 12:02. Просмотров 755. Ответов 10
Метки нет (Все метки)

Всем привет, помогите написать функцию для побитной записи в wav контейнер. Собственно есть код представления звуковой волны в графическом виде:
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 "stdafx.h"
#include <math.h>
#include <iostream>
//#include <Wincon.h>
#include <Windows.h>
#include <cstdio>
 
 
double PI=3.14;
class Program {
    public: 
 
        static void Wave() {
            double *data = new double[75]; // Инициализируем массив.
            for (int index = 1; index < 76; index++) { // Вычисляем данные для всего массива.
                data[index-1] = Sine(index, PI * 2 * 2.0 / 75); // Период разделенный на частоту дискретизации.
            }
            Draw(data);
            std::cin.get(); // Ждем нажатия любой клавиши.
        }
 
        static double Sine(int index, double frequency) {
            return sin(frequency * index);
        }
 
        static void Draw (double *data) {
            //Console.BufferHeight = 25; // Изменяем длину буфера консоли чтобы избавиться от ползунка.
            //Console.CursorVisible = false; // отключаем курсор для красоты.
            for (int y = 0; y < 19; y++) {// Выписываем индексы уровня звука.
                COORD coord;
                coord.X = 77;
                coord.Y = y+5;
                SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);// Устанавливаем курсор в нужную позицию.
                std::cout << (9 - y); // Выписываем номер индекса уровня.
            }
            for (int x = 0; x < 75; x++) { // Перебираем все элементы массива
                COORD coord;
                coord.X = x;
                coord.Y = x % 3;
                SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//Устанавливаем курсор в нужную точку.
                std::cout << (x + 1); // пишем индексы элемента.
                int point = (int)(data[x] * 9); // Вычисляем уровень и приводим его к амплитуде от -9 до 9.
                int step = (point > 0)? -1 : 1; // Узнаем в какую сторону 0.
                for (int y = point; y != step; y += step) {// перебираем столбик
                    COORD coord;
                    coord.X = x;
                    coord.Y = point + 14 - y;
                    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
//Устанавливаем курсор в нужную позицию.
                    std::cout << ("в–€"); // Рисуем точку.
                }
            }
        }
};
int main()
{
    Program r;
    r.Wave();
    //std::cin.get(); 
 
    return 0;
}
теперь нужно переписать побитно в wav, чтобы потом можно было проиграть. Есть пример подобного кода на С#, буду очень признателен если ктото сможет перевести на С++(нужен имено С++ а не включение классов С#) Вот код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void SaveWave(Stream stream) {
            BinaryWriter writer = new BinaryWriter(stream);
            short frameSize = (short)(16 / 8);
            writer.Write(0x46464952);
            writer.Write(36 + data.Length * frameSize);
            writer.Write(0x45564157);
            writer.Write(0x20746D66);
            writer.Write(16);
            writer.Write((short)1);
            writer.Write((short)1);
            writer.Write(sampleRate);
            writer.Write(sampleRate * frameSize);
            writer.Write(frameSize);
            writer.Write((short)16);
            writer.Write(0x61746164);
            writer.Write(data.Length * frameSize);
            for (int index = 0; index < data.Length; index++) {
                foreach (byte element in BitConverter.GetBytes(data[index])) {
                    stream.WriteByte(element);
                }
            }
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
THE--MASTER
Заблокирован
24.02.2014, 14:29     Побитная запись в контейнер wav #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
#include <tchar.h>
#include <fstream>
 
int _tmain(int argc, _TCHAR* argv[])
{
    std::fstream fs(L"C:\\1.wav", std::ios::out | std::ios::binary);
    if(!fs.is_open())
        return 0;
    //ЗАПИСЬ INT В ФАЙЛ
    int x = 45;
    fs.write((char*)&x, sizeof(x));
    //ЗАПИСЬ СТРОКИ В ФАЙЛ
    std::string str = "HELLO";
    //сначала пишем её длину, чтоб можно было её прочитать
    int len = str.size();
    fs.write((char*)&len, sizeof(len));
    //теперь сами симвлы
    fs.write((char*)str.c_str(), len + 1); //len + 1 - единица на NULL в конце строки.
    //.. и так далее
 
    //В двух словах таким макаром пишешь сначала весь заголовок WAV, а потом и сами данные
    fs.close();
    return 0;
}
Sonance
6 / 6 / 3
Регистрация: 15.02.2013
Сообщений: 55
24.02.2014, 16:33  [ТС]     Побитная запись в контейнер wav #3
Чегото я не догоняю, добавил в класс структуру заголовка WAV, написал функцию записи заголовка в файл, но чтото в файл вместо нужных символов пишет буквы "M" непойму в чем дело
Вот код:
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "stdafx.h"
#include <math.h>
#include <iostream>
//#include <Wincon.h>
#include <Windows.h>
#include <cstdio>
 
 
double PI=3.14;
class Program {
    public: 
 
        static void Wave() {
            double *data = new double[75]; // Инициализируем массив.
            for (int index = 1; index < 76; index++) { // Вычисляем данные для всего массива.
                data[index-1] = Sine(index, PI * 2 * 2.0 / 75); // Период разделенный на частоту дискретизации.
            }
            WAVHEADER stream;
            SaveWave(data, 8000);
            Draw(data);
            std::cin.get(); // Ждем нажатия любой клавиши.
        }
 
        static double Sine(int index, double frequency) {
            return sin(frequency * index);
        }
 
        static void Draw (double *data) {
            //Console.BufferHeight = 25; // Изменяем длину буфера консоли чтобы избавиться от ползунка.
            //Console.CursorVisible = false; // отключаем курсор для красоты.
            for (int y = 0; y < 19; y++) {// Выписываем индексы уровня звука.
                COORD coord;
                coord.X = 77;
                coord.Y = y+5;
                SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);// Устанавливаем курсор в нужную позицию.
                std::cout << (9 - y); // Выписываем номер индекса уровня.
            }
            for (int x = 0; x < 75; x++) { // Перебираем все элементы массива
                COORD coord;
                coord.X = x;
                coord.Y = x % 3;
                SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//Устанавливаем курсор в нужную точку.
                std::cout << (x + 1); // пишем индексы элемента.
                int point = (int)(data[x] * 9); // Вычисляем уровень и приводим его к амплитуде от -9 до 9.
                int step = (point > 0)? -1 : 1; // Узнаем в какую сторону 0.
                for (int y = point; y != step; y += step) {// перебираем столбик
                    COORD coord;
                    coord.X = x;
                    coord.Y = point + 14 - y;
                    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); //Устанавливаем курсор в нужную позицию.
                    std::cout << ("#"); // Рисуем точку.
                }
            }
        }
        struct WAVHEADER{
            // WAV-формат начинается с RIFF-заголовка:
            char chunkId[4];// Содержит символы "RIFF" в ASCII кодировке
            unsigned long chunkSize;// 36 + subchunk2Size, или более точно:
            char format[4];// Содержит символы "WAVE"
            char subchunk1Id[4];// Содержит символы "fmt "
            unsigned long subchunk1Size;// 16 для формата PCM.
            unsigned short audioFormat;// Для PCM = 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" содержит аудио-данные и их размер.Содержит символы "data"
            unsigned long subchunk2Size;// Количество байт в области данных.
            // Далее следуют непосредственно Wav данные.
            //unsigned short data;
};
 
        static void SaveWave( double *data, int sampleRate){
            short frameSize = (short)(16 / 8);
            WAVHEADER stream;
            stream.chunkId[4] = ('R','I','F','F');
            stream.chunkSize = (36 + sizeof(data) * frameSize);
            stream.format[4] = ('W','A','V','E');
            stream.subchunk1Id[4] = ('f','m','t',' ');
            stream.subchunk1Size = 16;
            stream.audioFormat = ((short)1);
            stream.numChannels = ((short)1);
            stream.sampleRate = sampleRate;
            stream.byteRate = (sampleRate * frameSize);
            stream.blockAlign = frameSize;
            stream.bitsPerSample = ((short)16);
            stream.subchunk2Id[4] = ('D','A','T','A');
            stream.subchunk2Size = (sizeof(data) * frameSize);
 
            FILE *f1;
            f1 = fopen("1.wav", "w+b");
            fwrite(&stream, sizeof(stream), 1, f1);
            fcloseall();
        }
 
};
int main()
{
    Program r;
    r.Wave();
    
    //std::cin.get(); 
 
    return 0;
}
Вот что написано в сохроняемом WAV файле: " ММММ, ММММEМММ   @ Ђ>   ММММ "
THE--MASTER
Заблокирован
24.02.2014, 16:46     Побитная запись в контейнер wav #4
Цитата Сообщение от Sonance Посмотреть сообщение
Вот что написано в сохроняемом WAV файле: " ММММ, ММММEМММ @ Ђ> ММММ "
А что ты хотел увидеть блокнотом в бинарном файле?
Я же тебе говорил, используй std::fstream Для записи в файл, не будь колхозником

тут
C++
1
2
3
4
 FILE *f1;
            f1 = fopen("1.wav", "w+b");
            fwrite(&stream, sizeof(stream), 1, f1);
            fcloseall();
ты пытаешься записать только заголовок, сами данные ты не пишешь.

Что ты вообще хочешь сделать?
Давай свой массив данных сюда - покажу как надо записывать )))
Sonance
6 / 6 / 3
Регистрация: 15.02.2013
Сообщений: 55
24.02.2014, 17:06  [ТС]     Побитная запись в контейнер wav #5
Тут я и пытался записать хотябы заголовок(если обычный wav блокнотом открыть заголовки различаемы), масив data в функции Wave()(самая первая функция в коде). Если не сложно покажи как записать в файл Заголовок из структуры в моей функции, дальше думаю уже сам разберусь.


Вот так в обычных WAV в начале: " RIFFvК WAVEfmt    D¬ €X   smpl< "
THE--MASTER
Заблокирован
24.02.2014, 17:56     Побитная запись в контейнер wav #6
Сообщение было отмечено автором темы, экспертом или модератором как ответ
так и быть, ща потрачу время ... всё равно работать сегодня мне влом )))

Добавлено через 30 минут
Да прибудет со мной сила

C++
1
2
3
4
5
6
7
8
9
10
#include <tchar.h>
#include "WavProcessor.h"
 
int _tmain(int argc, _TCHAR* argv[])
{
    WavProcessor wp;
    if(wp.ReadWav(L"C:\\1.wav"))
        wp.SaveWav(L"C:\\out.wav");
    return 0;
}
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
#pragma once
#include <string>
#include <fstream>
 
struct WAVHEADER
{   
    char chunkId[4];
    unsigned long chunkSize;    
    char format[4]; 
    char subchunk1Id[4];    
    unsigned long subchunk1Size;    
    unsigned short audioFormat; 
    unsigned short numChannels; 
    unsigned long sampleRate;   
    unsigned long byteRate; 
    unsigned short blockAlign;  
    unsigned short bitsPerSample;   
    char subchunk2Id[4];    
    unsigned long subchunk2Size;    
};
 
class WavProcessor
{
public:
    WavProcessor();
    ~WavProcessor();
 
    bool ReadWav(std::wstring fileName);
    bool SaveWav(std::wstring targetFileName);
 
private:    
    WAVHEADER *wh;
    short *waveData;
    size_t dataLen;
};
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
#include "WavProcessor.h"
 
 
WavProcessor::WavProcessor() : wh(0), waveData(0)
{
}
 
 
WavProcessor::~WavProcessor()
{
    if(wh)
        delete wh;
    if(waveData)
        delete waveData;
}
 
bool WavProcessor::ReadWav( std::wstring fileName )
{   
    if(wh)
        delete wh;
    if(waveData)
        delete waveData;
 
    std::fstream fs(fileName.c_str(), std::ios::in | std::ios::binary);
    if(!fs.is_open())
        return false;
 
    wh = new WAVHEADER;
    fs.read((char*)wh, sizeof(WAVHEADER));      
    dataLen = wh->subchunk2Size;
    waveData = new short[dataLen];
    fs.read((char*)waveData, dataLen);
    //ЭЙ Sonance, в общем смари. В 16 bit каждое значение signed short
    //В стерео режиме данные идут так: 2 байта лево, 2 байта право, 2 байта лево, 2 байта право
    //Ну это на тот случай, если ты захочешь что - то с этими данными делать ....
    //Не забудь мне плюсиков под моим ником поставить и записать мне "лучший ответ" :-))))))))))
    fs.close();
    
    return true;
}
 
bool WavProcessor::SaveWav( std::wstring targetFileName )
{
    if(!waveData || !wh)
        return false;
 
    std::fstream fs(targetFileName.c_str(), std::ios::out | std::ios::binary);
    if(!fs.is_open())
        return false;
 
    fs.write((char*)wh, sizeof(WAVHEADER));
    fs.write((char*)waveData, dataLen);
    fs.close();
 
    return true;
}
Sonance
6 / 6 / 3
Регистрация: 15.02.2013
Сообщений: 55
24.02.2014, 22:31  [ТС]     Побитная запись в контейнер 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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "stdafx.h"
#include <math.h>
#include <iostream>
#include <Windows.h>
 
 
 
double PI=3.14159265358979323846;
class Generator {
    public: 
 
        static void Wave() {
            int sampleRate = 8000;// частота дискретизации.
            short *data = new short[sampleRate]; // Инициализируем массив 16 битных значений
            double frequency = PI * 2 * 440.0 / sampleRate; // Рассчитываем требующуюся частоту.
            for (int index = 0; index < sampleRate; index++) { 
                 data[index] = (short)(Sine(index, frequency) * SHRT_MAX);// Приводим уровень к амплитуде от 32767 до -32767.
            }
            SaveWave(data, sampleRate);
        }
 
        static double Sine(int index, double frequency) {//Расчет значений для синусоидальной волны
            return sin(frequency * index);
        }
        //Header WAV файла
        struct WAVHEADER{
            // WAV-формат начинается с RIFF-заголовка:
            char chunkId[4];// Содержит символы "RIFF" в ASCII кодировке
            unsigned long chunkSize;// 36 + subchunk2Size, или более точно:
            char format[4];// Содержит символы "WAVE"
            char subchunk1Id[4];// Содержит символы "fmt "
            unsigned long subchunk1Size;// 16 для формата PCM.
            unsigned short audioFormat;// Для PCM = 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" содержит аудио-данные и их размер.Содержит символы "data"
            unsigned long subchunk2Size;// Количество байт в области данных. numSamples * numChannels * bitsPerSample/8
        };
        //Функция записи WAV файла
        static void SaveWave( short *data, int sampleRate){
            short frameSize = (short)(16 / 8);
            WAVHEADER stream;
            stream.chunkId[0] = 'R';
            stream.chunkId[1] = 'I';
            stream.chunkId[2] = 'F';
            stream.chunkId[3] = 'F';
            stream.chunkSize = (36 + sampleRate * frameSize);
            stream.format[0] = 'W';
            stream.format[1] = 'A';
            stream.format[2] = 'V';
            stream.format[3] = 'E';
            stream.subchunk1Id[0] = 'f';
            stream.subchunk1Id[1] = 'm';
            stream.subchunk1Id[2] = 't';
            stream.subchunk1Id[3] = ' ';
            stream.subchunk1Size = (16);
            stream.audioFormat = ((short)1);
            stream.numChannels = ((short)1);
            stream.sampleRate = sampleRate;
            stream.byteRate = (sampleRate * frameSize);
            stream.blockAlign = frameSize;
            stream.bitsPerSample = ((short)16);
            stream.subchunk2Id[0] = 'd';
            stream.subchunk2Id[1] = 'a';
            stream.subchunk2Id[2] = 't';
            stream.subchunk2Id[3] = 'a';
            stream.subchunk2Size = (sampleRate * frameSize);
 
            FILE *f1;
            f1 = fopen("test.wav", "w+b");
            fwrite(&stream, sizeof(stream), 1, f1);
            for (int i = 0; i < sampleRate; i++){   
                    fwrite(&data[i], sizeof(short),1, f1);//записываем байты элемента i массива data
            }
            fclose(f1);
        }
 };
int main()
{
    Generator r;
    r.Wave();
    std::cin.get(); 
    return 0;
}
Xaviichi
0 / 0 / 0
Регистрация: 20.12.2014
Сообщений: 18
20.12.2014, 17:45     Побитная запись в контейнер wav #8
Sonance, спасибо за код, я сейчас работаю с wav-файлами и твой код очень мне пригодился
Такой вопрос: в 17 строке есть переменная
Цитата Сообщение от Sonance Посмотреть сообщение
SHRT_MAX
. На что она влияет и где ты ее объявил?
Croessmah
Модератор
Эксперт CЭксперт С++
13052 / 7315 / 814
Регистрация: 27.09.2012
Сообщений: 18,052
Записей в блоге: 3
Завершенные тесты: 1
20.12.2014, 18:41     Побитная запись в контейнер wav #9
Цитата Сообщение от Xaviichi Посмотреть сообщение
На что она влияет и где ты ее объявил?
http://www.cplusplus.com/reference/climits/
SHRT_MAX - Maximum value for an object of type short int
Xaviichi
0 / 0 / 0
Регистрация: 20.12.2014
Сообщений: 18
20.12.2014, 21:29     Побитная запись в контейнер wav #10
Спасибо! Все понял, понял также и то, почему отладчик программы ругался на переменную
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.12.2014, 22:57     Побитная запись в контейнер wav
Еще ссылки по теме:
C++ контейнер
C++ Стегография. Формат .wav
микширование файлов wav C++
Редактирование wav файлов в С++ C++
C++ Шумящие биты в WAV

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

Или воспользуйтесь поиском по форуму:
raxp
10155 / 6542 / 477
Регистрация: 28.12.2010
Сообщений: 21,166
Записей в блоге: 1
20.12.2014, 22:57     Побитная запись в контейнер wav #11
Побитная запись в контейнер wav
побайтная.
Yandex
Объявления
20.12.2014, 22:57     Побитная запись в контейнер wav
Ответ Создать тему
Опции темы

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