Skip to content

Instantly share code, notes, and snippets.

@alexey-detr
Last active September 29, 2015 20:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexey-detr/1664073 to your computer and use it in GitHub Desktop.
Save alexey-detr/1664073 to your computer and use it in GitHub Desktop.
Читаем заголовок WAV файла на C#
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace WavFormatCSharp
{
[StructLayout(LayoutKind.Sequential)]
// Структура, описывающая заголовок WAV файла.
internal class WavHeader
{
// WAV-формат начинается с RIFF-заголовка:
// Содержит символы "RIFF" в ASCII кодировке
// (0x52494646 в big-endian представлении)
public UInt32 ChunkId;
// 36 + subchunk2Size, или более точно:
// 4 + (8 + subchunk1Size) + (8 + subchunk2Size)
// Это оставшийся размер цепочки, начиная с этой позиции.
// Иначе говоря, это размер файла - 8, то есть,
// исключены поля chunkId и chunkSize.
public UInt32 ChunkSize;
// Содержит символы "WAVE"
// (0x57415645 в big-endian представлении)
public UInt32 Format;
// Формат "WAVE" состоит из двух подцепочек: "fmt " и "data":
// Подцепочка "fmt " описывает формат звуковых данных:
// Содержит символы "fmt "
// (0x666d7420 в big-endian представлении)
public UInt32 Subchunk1Id;
// 16 для формата PCM.
// Это оставшийся размер подцепочки, начиная с этой позиции.
public UInt32 Subchunk1Size;
// Аудио формат, полный список можно получить здесь http://audiocoding.ru/wav_formats.txt
// Для PCM = 1 (то есть, Линейное квантование).
// Значения, отличающиеся от 1, обозначают некоторый формат сжатия.
public UInt16 AudioFormat;
// Количество каналов. Моно = 1, Стерео = 2 и т.д.
public UInt16 NumChannels;
// Частота дискретизации. 8000 Гц, 44100 Гц и т.д.
public UInt32 SampleRate;
// sampleRate * numChannels * bitsPerSample/8
public UInt32 ByteRate;
// numChannels * bitsPerSample/8
// Количество байт для одного сэмпла, включая все каналы.
public UInt16 BlockAlign;
// Так называемая "глубиная" или точность звучания. 8 бит, 16 бит и т.д.
public UInt16 BitsPerSample;
// Подцепочка "data" содержит аудио-данные и их размер.
// Содержит символы "data"
// (0x64617461 в big-endian представлении)
public UInt32 Subchunk2Id;
// numSamples * numChannels * bitsPerSample/8
// Количество байт в области данных.
public UInt32 Subchunk2Size;
// Далее следуют непосредственно Wav данные.
}
class Program
{
static void Main(string[] args)
{
var header = new WavHeader();
// Размер заголовка
var headerSize = Marshal.SizeOf(header);
var fileStream = new FileStream("Slipknot - Three Nil.wav", FileMode.Open, FileAccess.Read);
var buffer = new byte[headerSize];
fileStream.Read(buffer, 0, headerSize);
// Чтобы не считывать каждое значение заголовка по отдельности,
// воспользуемся выделением unmanaged блока памяти
var headerPtr = Marshal.AllocHGlobal(headerSize);
// Копируем считанные байты из файла в выделенный блок памяти
Marshal.Copy(buffer, 0, headerPtr, headerSize);
// Преобразовываем указатель на блок памяти к нашей структуре
Marshal.PtrToStructure(headerPtr, header);
// Выводим полученные данные
Console.WriteLine("Sample rate: {0}", header.SampleRate);
Console.WriteLine("Channels: {0}", header.NumChannels);
Console.WriteLine("Bits per sample: {0}", header.BitsPerSample);
// Посчитаем длительность воспроизведения в секундах
var durationSeconds = 1.0 * header.Subchunk2Size / (header.BitsPerSample / 8.0) / header.NumChannels / header.SampleRate;
var durationMinutes = (int)Math.Floor(durationSeconds / 60);
durationSeconds = durationSeconds - (durationMinutes * 60);
Console.WriteLine("Duration: {0:00}:{1:00}", durationMinutes, durationSeconds);
Console.ReadKey();
// Освобождаем выделенный блок памяти
Marshal.FreeHGlobal(headerPtr);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment