Чи існує Windows, еквівалентна Linux "aplay", яка прийме аудіо потоку бітів і виходу?


2

я спостерігав Комп'ютерний відеофайл про код гольф і чіптуни і був зацікавлений у запуску наведений приклад коду , але вона спирається на aplay, утиліта Linux для драйвера звукової карти ALSA, і я хотів би запустити її на Windows 7. Чи є еквівалентна програма або утиліта для Windows 7+ (бажано, але не обов'язково ОС), яка займе потік байтів і конвертувати його в аудіопотік?

Відповіді:


0

ж :)

Я знайшов, що ви можете використовувати ffmpeg для його перетворення

ffmpeg -f u8 -i music.raw music.wav

Потім скористайтеся тим, що ви хочете відтворити

Тепер, я намагався трубопроводу його безпосередньо (vlc дозволяє введення на stdin, але він не буде читати вихідні дані, принаймні, не без аргументів я не знаю, як дати йому LOL) \ t

music.exe | ffmpeg ... -i pipe:1 | vlc.exe -

але ffmpeg сказав, що труба не мала достатньо місця (я спробував трубку: 0, так як я не був на 100% впевнений, що це для stdin на вікнах ...)

тому в кінцевому підсумку я перенаправляв music.exe на файл music.raw на невелику кількість часу ( music.exe > music.raw ) Тоді я міг би використовувати це, щоб труба прямо з ffmpeg до vlc

ffmpeg.exe -f u8 -i music.raw -f wav pipe:1 | vlc.exe -

Відповідь така ж гарна, як і будь-яка інша, тому я позначу її. Я думаю, що справжня відповідь полягає в тому, що на вікнах немає хорошого прямого рішення для труб
Ken Bellows

Я хотів би прокоментувати це на вашому, але у мене немає 50 реп. unix.stackexchange.com/questions/205107/… Я знайшов вище з пошуком Google, тоді як команда може бути трохи більше, ніж ./a | aplay, теоретично можна зробити це без необхідності зберігати файл. Потім можна додати команду до файлу makefile / batch і т.д.
FreeER

Основна проблема, яку я знайшов при використанні play.exe від SoX, полягає в тому, що він має важкий інтерфейс зі звуковими драйверами Windows. Може бути, я просто не знаю достатньо про SoX, але я ще не зрозумів, як отримати play.exe для роботи без просто кинути помилку
Ken Bellows

hm, завантаження, яке я отримав для sox, насправді не було play.exe, але я знайшов, що ви можете просто вказати вихід "-t -waveaudio default" замість файлу. btw, я кинув все це на Dropbox, якщо вас цікавить: dropbox.com/sh/ibb924waxkqga04/AAAa3yxp_lf7_awM2eY30bPqa?dl=0
FreeER

1
Я тільки що дізнався, що він дійсно працює з ffmpeg, якщо ви не вказали номер труби. Просто введіть a.exe | ffmpeg.exe -ar 8000 -f u8 -i pipe: -f wav pipe: | vlc.exe - і ви повинні добре йти. Опція -ar встановлює частоту дискретизації до 8000 Гц. За замовчуванням ffmpeg використовує 44100 Гц.
maddin45

3

Я дивився точно такий же відео і був дуже розчарований, що я не міг знайти програму для вікон, які поводяться, як грати в цьому прикладі.

Зрештою, я написав одну, використовуючи C ++ і OpenAL . Я надішлю код нижче. Вам доведеться зв'язати бібліотеку OpenAL для створення виконуваного файлу. Бібліотека є частиною OpenAL Core SDK, яку можна завантажити з веб-сайту.

Якщо ви просто хочете виконати, ви можете завантажити його тут . Шукати yalpa.exe.

Синтаксис

Припустимо, ви використовуєте мій виконуваний файл yalpa.exe. Потім ви можете обробити свої необроблені аудіодані, передавши їх у yalpa:

a.exe | yalpa.exe

В якості альтернативи можна спочатку записати аудіодані у файл і передати цей файл до stdin:

yalpa.exe < my_audio.raw

Примітка: yalpa працює в cmd, але не в PowerShell. Труби, здається, обробляються інакше (див це питання, пов'язане з SO ).

Код:

Відмова від відповідальності: Я не можу гарантувати, що цей код на 100% вільний від помилок, але я перевірив його на двох різних машинах з Windows 7 і Windows 10 відповідно. Він був скомпільований і зв'язаний за допомогою компілятора Visual Studio 2013. \ t Я також зміг скомпілювати його за допомогою g ++ на Cygwin, але OpenAL не вдалося під час виконання через проблеми з pulseaudio.

Ви можете вільно редагувати та використовувати свій код.

#include <iostream>
#include <cstdio>
#include <cstdint>
#include <thread>
#include <chrono>

#if defined _WIN32
#include <al.h>
#include <alc.h>
#include <io.h>
#include <fcntl.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#endif

#if 0 || defined _DEBUG
#define AL_CHECK_ERROR(msg) (checkALError(msg))
#else
#define AL_CHECK_ERROR(msg)
#endif

const uint8_t numBuf = 3;
const ALsizei bufSize = 1000;
const ALenum format = AL_FORMAT_MONO8;
const ALsizei freq = 8000;
char readBuf[bufSize]; 

void checkALError(const char * msg)
{
    while (ALuint err = alGetError() != AL_NO_ERROR)
        std::cerr << "Caught AL Error at " << msg << ": " << err << "\n";
}

ALsizei fillBufferFromStdin(ALuint buf)
{
    // read
    const ALsizei bytesRead = (ALsizei) fread(readBuf, sizeof(uint8_t), bufSize, stdin);
    // copy to OpenAL buffer
    alBufferData(buf, format, (void *) readBuf, bytesRead, freq);
    AL_CHECK_ERROR("buffer data");
    return bytesRead;
}

void updateBuffers(ALuint src, ALuint bufs[numBuf])
{
    ALint srcState;
    do
    {
        // wait until a buffer is free
        ALint val = 0;
        do 
        {
            alGetSourcei(src, AL_BUFFERS_PROCESSED, &val);
            AL_CHECK_ERROR("get num processed");
            if (val > 0) break;
            // sleep for a quarter of the duration a buffer plays
            std::this_thread::sleep_for(std::chrono::milliseconds((bufSize / freq) * 1000 / 4));
        } while (true);
        while (val--)
        {
            // remove oldest buffer from queue and get its id
            ALuint buf;
            alSourceUnqueueBuffers(src, 1, &buf);
            AL_CHECK_ERROR("unqueue buffer");
            // fill buffer
            const ALsizei bytesRead = fillBufferFromStdin(buf);
            // add buffer to queue
            alSourceQueueBuffers(src, 1, &buf);
            AL_CHECK_ERROR("queue buffer");
            // if end of stdin was reached, return
            if (bytesRead < bufSize) return;
        }
        // check if source is still playing
        alGetSourcei(src, AL_SOURCE_STATE, &srcState);
    } while (AL_PLAYING == srcState);
}

int main(int argc, char * argv[])
{
    std::cout << "OpenAL test project\n";
    // set stdin to binary mode
#ifdef _WIN32
    _setmode(_fileno(stdin), _O_BINARY);
#else
    freopen(nullptr, "rb", stdin);
#endif

    // initialization: open default device
    ALCdevice * dev = alcOpenDevice(nullptr);
    // reset error state
    AL_CHECK_ERROR("open device");
    // create a context
    ALCcontext * context = alcCreateContext(dev, nullptr);
    AL_CHECK_ERROR("create context");
    alcMakeContextCurrent(context);
    AL_CHECK_ERROR("activate context");
    // create buffers for audio streaming
    ALuint bufs[numBuf];
    alGenBuffers(numBuf, bufs);
    AL_CHECK_ERROR("create buffer");
    // create source to play buffer
    ALuint src;
    alGenSources(1, &src);
    AL_CHECK_ERROR("create source");

    // initially fill buffers
    for (uint8_t i = 0; i < numBuf; ++i) fillBufferFromStdin(bufs[i]);
    alSourceQueueBuffers(src, numBuf, bufs);
    AL_CHECK_ERROR("queue buffer");
    // play source
    alSourcePlay(src);
    AL_CHECK_ERROR("play");
    // fill buffers in loop
    updateBuffers(src, bufs);
    // when stream is read completely, wait until source stops playing
    ALint srcState;
    do
    {
        alGetSourcei(src, AL_SOURCE_STATE, &srcState);
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    } while (AL_PLAYING == srcState);


    // delete source
    alDeleteSources(1, &src);
    AL_CHECK_ERROR("delete source");
    // delete buffers
    alDeleteBuffers(numBuf, bufs);
    AL_CHECK_ERROR("delete buffer");
    // destroy context
    alcDestroyContext(context);
    AL_CHECK_ERROR("destroy context");
    // close device
    alcCloseDevice(dev);
    AL_CHECK_ERROR("close device");

    std::cout << "Exiting\n";
    return 0;
}

1

Використовуючи vlc і деякі аргументи командного рядка, я скопіював-вставив з Інтернету, ви можете відтворити функціональність гри на вікнах.

audio.exe | vlc --demux=rawaud --rawaud-channels 2 --rawaud-samplerate 8000 -

Кредит повинен йти цей пост і відповідь FreeER.


де параметр джерела бітового потоку?
nicolay.anykienko

0

Для потомства: здається, що це не дуже гарне рішення, але інший приблизний, який я знайшов, повинен був використовувати SoX з наступними параметрами для створення файлу .wav:

./a.exe | sox -t raw -b 16 -e signed -r 8000 - test.wav

Це створює дуже великий файл дуже швидко, тому не дозволяйте йому працювати занадто довго. Близько 10 секунд на моїй машині (Intel i7 3.4GHz процесор) генерується близько 2 годин аудіо (~ 125 Кб).


Не знаючи сокс, ви могли б сказати йому, на виході stdout потім перетягніть його на head -c <bytes> для обмеження виведення на кількість байтів. samples/second × bytes/channel/sample × channels × seconds = bytes. Ви втратите кілька зразків через заголовок, але це швидкий і брудний метод. Інакше sox має команду, яка дозволить вам обрізати вхід: sox <options> - test.wav trim 0 60, що означає, що він пропустить 0 секунд і займе 60 секунд від входу.
sleblanc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.