मैंने ठीक उसी वीडियो को देखा और बहुत निराश था कि मुझे इस उदाहरण में aplay की तरह व्यवहार करने वाली खिड़कियों के लिए कोई प्रोग्राम नहीं मिला।
अंत में, मैंने खुद को C ++ और OpenAL का उपयोग करके लिखा । मैं नीचे दिए गए कोड को पोस्ट करूंगा। निष्पादन योग्य बनाने के लिए आपको OpenAL लाइब्रेरी से लिंक करना होगा। लाइब्रेरी ओपन कोर एसडीके का हिस्सा है जिसे आप उनकी वेबसाइट से डाउनलोड कर सकते हैं।
यदि आप केवल निष्पादन योग्य चाहते हैं, तो आप इसे यहां डाउनलोड कर सकते हैं । के लिए देखो yalpa.exe
।
वाक्य - विन्यास
मान लीजिए कि आप मेरे निष्पादन योग्य का उपयोग करते हैं yalpa.exe
। तब आप अपने कच्चे ऑडियो डेटा को यल्पा में पाइप करके संसाधित कर सकते हैं:
a.exe | yalpa.exe
वैकल्पिक रूप से आप पहले ऑडियो डेटा को एक फाइल में लिख सकते हैं और उस फाइल को याल्पा के स्टड पर पास कर सकते हैं:
yalpa.exe < my_audio.raw
नोट: yalpa cmd में काम करता है, लेकिन PowerShell में नहीं। पाइप्स को वहां अलग तरह से संभाला जाने लगता है (देखें इससे संबंधित SO प्रश्न )।
कोड:
अस्वीकरण: मैं गारंटी नहीं दे सकता कि यह कोड 100% बग-मुक्त है, लेकिन मैंने इसे क्रमशः विंडोज 7 और विंडोज 10 के साथ दो अलग-अलग मशीनों पर परीक्षण किया। यह विजुअल स्टूडियो 2013 कंपाइलर का उपयोग करके संकलित और जुड़ा हुआ था। मैं इसे Cygwin पर g ++ का उपयोग करके भी संकलित करने में सक्षम था, लेकिन पल्सीडियो के साथ समस्याओं के कारण OpenAL रनटाइम में विफल रहा।
मेरे कोड को संपादित करने और उसका उपयोग करने के लिए स्वतंत्र महसूस करें।
#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;
}