Если вам известна файловая структура RIFF, возможно, вы уже знаете, как в ней хранится звук PCM.
Общий формат - 16-битный стерео PCM. В этом случае каждая выборка составляет 2 байта, и две выборки принадлежат друг другу (слева + справа). Но вы должны проверить формат чанка для точного формата. Но я полагаю, что сейчас вы управляете 16-битным стереофоническим PCM-WAV-файлом.
Вы можете манипулировать выборками, используя 16-битный целочисленный тип (short, _int16, int16_t). Например, чтобы уменьшить громкость, вы можете разделить каждый семпл на некоторое число. Но если вы разделите его на 2, это не означает, что оно станет вдвое громче. Смотрите этот пост .
Если вы просто манипулируете семплами, заголовки RIFF не меняются, поэтому вы можете скопировать их из источника.
Если вы хотите удалить или добавить сэмплы, размер фрагмента данных изменится, а также размер всего файла в заголовке рифа.
Например, вы можете просто отбросить каждый 10-й пример, затем скопировать 9 * 4 = 36 байтов из блока данных, пропустить 4 байта, скопировать 36 байтов и так далее. Но если вы сделаете что-то подобное, это будет звучать очень плохо. Лучший способ услышать результат - манипулировать синусоидальной волной. Если синус не совсем правильный, его будет легко услышать. Чтобы правильно отбросить выборки, вам, вероятно, нужно использовать быстрое преобразование Фурье (БПФ).
В качестве дополнения на основе ваших комментариев добавляю следующее:
См. C ++ Двоичный файл ввода / вывода для быстрого ознакомления с файловым вводом / выводом. Ваша ссылка с описанием формата RIFF выглядит правильно, но не завершена. Согласно этому описанию заголовок всегда составляет 44 байта. Но можно добавить больше информации в шапку.
Что вам нужно сделать, это пропустить первые 12 байтов (хотя вы можете использовать его, чтобы проверить, является ли файл действительно волновым файлом).
А затем в цикле прочитать имя и размер следующего куска. Если это фрагмент, который вы знаете ('fmt' или 'data'), вы можете обработать его, в противном случае пропустите его.
Так это может выглядеть, например:
ifstream myFile ("example.wav", ios::in | ios::binary);
char buffer[12];
myFile.read (buffer, 12); // skip RIFF header
char chunkName[5];
unsigned long chunksize;
while (myFile.read (chunkName, 4)) {
chunkName[4]='\0'; // add trailing zero
myFile.read((char*)&chunksize, 4);
// if chunkname is 'fmt ' or 'data' process it here,
// otherwise skip any unknown chunk:
myFile.seekg(chunksize, ios_base::cur);
}