LINUX.ORG.RU

Разбор аудиофайлов и создаие аудиопотока.

 


0

1

Собственно сабж.
С разбором файлов на самом деле трудностей особых нет, секции, метаданные данные разбирать не сложно если документация хорошая.

Но вот я добрался допустим до самих аудиоданных и делать просто не знаю что с ними.
Специально взял формат WAV PCM (правда BitsPerSample у него 24bit ну и ладно наверное) 2 канала, как его читать? ()

В документации написано

данные           размер секции     коммент
--------------------------------------------------------------
sampled data 	   M*Nc*Ns        Nc*Ns channel-interleaved M-byte samples

Вот я по файлу прошел вычислил размер/вынес эти данные в байтовый массив.
Как вот это разобрать какую часть данных в какой канал пихать и.. его же не нужно декодировать, верно?

И еще вот я допустим разберусь с PCM, а там еще есть всякие IEEE float32/64 - как с ними быть? Или вот например захочу написать декодер vorbis или какого нибудь иного lossy кодека - оно так же при декодированнии преобразовывается в PCM или во что то иное?

И еще: как время аудиофайла вычислить,
есть вот размер секции ck_size = 2498346
и размер блока nBlockAlign = 6
я просто делю размер ck_size / nBlockAlign /* 9.441972789115646 */ и примерно 9 сек. и должно быть.
Я правильно считаю или нет?

♪♩♫♪♫♩

★★★
Ответ на: комментарий от uin

уфф...

такое ощущение, что ты не дочитав букварь перешел на ядерную физику.

это и есть десятичная, f значит «float».

waker ★★★★★
()
Ответ на: комментарий от uin

после кратковременного гугления, выяснилось что в ноде есть вот это:

buf.readFloatBE(offset[, noAssert])
buf.readFloatLE(offset[, noAssert])

т.е. писать свой конвертер не надо, просто из буфера выдергивай floats по нужному смещению в нужном формате.

если ты хочешь конвертировать вручную, то вот пример.

из файла читается массив floats (big-endian), в буфер. в буфере меняются байты местами, после чего из буфера float'ы уже достаются как little-endian. результат, как и ожидалось, корректный.

var fs = require('fs');

var buf = fs.readFileSync ("floats.bin");

for (var i = 0; i < buf.length; i+=4) {
    var a = buf[i];
    var b = buf[i+1];
    var c = buf[i+2];
    var d = buf[i+3];
    buf[i] = d;
    buf[i+1] = c;
    buf[i+2] = b;
    buf[i+3] = a;
    var fl = buf.readFloatLE(i);
    console.log (fl);
}
waker ★★★★★
()
Последнее исправление: waker (всего исправлений: 1)
Ответ на: комментарий от waker

Так а мне зачем конверсия то теперь

function IEEE_754_to_float(b0, b1, b2, b3) {
   let sign = (b0 >> 7) ? -1 : 1;
   let exponent = (b0 << 1) + (b1 >> 7) - 126;
   let fraction_bits = ((b1 & 0x7F) << 16) + (b2 << 8) + b3;
   
   var fraction = 0.5f;
   for (uint8_t ii = 0; ii < 24; ++ii) {
      fraction += ldexpf((fraction_bits >> (23 - ii)) & 1, -(ii + 1));
   }
   let significand = sign * fraction;
   
   return ldexpf(significand, exponent);
}

//data = be32fp => uint8_arr
IEEE_754_to_float(data[3], data[2], data[1], data[0])


И точно так же делать для le -> be можно наверное

man ldexpf

хм, понятно ладно разберусь

судя по всему, эта функция преобразует стандартный ieee754 float из массива байт в нативный сишный float (который может использовать другой стандарт).

Ну ведь мне же это и над, у меня нет char -ов которые можно просто переставить и потом как одно число 4 чара ипрочитать у меня есть массив байтов, а точнее вообще чисел которые можно только складывать умножать делить и заполнять нулями - все.

это и есть десятичная, f значит «float».

А, ну вот откудаж мне было знать

uin ★★★
() автор топика
Последнее исправление: uin (всего исправлений: 1)
Ответ на: комментарий от waker

Это только для ноды и только из local fs, но вообще возьму на заметку , благодарю.

uin ★★★
() автор топика
Ответ на: комментарий от uin

Так а мне зачем конверсия то теперь

я не знал, что ты уже решил проблему. отмечай тему как решенную.

А, ну вот откудаж мне было знать

у меня было ложное мнение, что ты знаешь C.

waker ★★★★★
()
Ответ на: комментарий от waker

Еще не решил пока

у меня было ложное мнение, что ты знаешь C.

Ну как знаю, немножко что то делал на нем, проблема в том что задачь под него нет пока. Идей нет чего бы на нем можно было сделать (хотя на самом деле есть одна, когда нибудь и до нее доберусь и тогда изучу язык получше) ну а вообще так то в нем все более менее понятно, но только 2е проблемы: какая то кусочечная-обрывочная документация и тяжело дебажить, какие то printf приходится везде распихивать что бы смотреть где чего приходит итд.

uin ★★★
() автор топика
Ответ на: комментарий от uin

какая то кусочечная-обрывочная документация и тяжело дебажить, какие то printf приходится везде распихивать что бы смотреть где чего приходит итд.

ну а не было мыслей, что можно взять нормальную документацию, и воспользоваться дебаггером?

waker ★★★★★
()
Ответ на: комментарий от waker

Короче, давай поговорим об этом в другой раз, ок?

Проблема решена следующим образом


var length = io.sampleFrames, channels = io.channels, data = $.getBytesArray('Uint8', byteOffset, byteLength)
   for (let i = 0, x = 0; i < length; i++) {
      for (let c = 0; c < channels; c++, x += 4)
         bufObj[c][i] = Bytes2Float32((data[x] << 24) + (data[(x + 1)] << 16) + (data[(x + 2)] << 8) + data[(x + 3)]);
   }

function Bytes2Float32(bytes) {
    var sign = (bytes & 0x80000000) ? -1 : 1;
    var exponent = ((bytes >> 23) & 0xFF) - 127;
    var significand = (bytes & ~(-1 << 23));

    if (exponent == 128) 
        return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);

    if (exponent == -127) {
        if (significand == 0) return sign * 0.0;
        exponent = -126;
        significand /= (1 << 22);
    } else significand = (significand | (1 << 23)) / (1 << 23);

    return sign * significand * Math.pow(2, exponent);
} 


То есть преобразовывать следовало беззнаковые числа, о чем подсказал оригинальный код на Си
Вот теперь я вижу плюсы статической типизации

Тебе спасибо за наводку, я что то на ту страницу не натыкался при гуглении

uin ★★★
() автор топика
Последнее исправление: uin (всего исправлений: 3)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.