问题标签 [xaudio2]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
vb.net - 在 Windows Phone 8.1 应用程序中生成音调或声音
我正在尝试在 Windows Phone 8.1 上以设定的频率和持续时间生成音调。跟进此处介绍的主题:在 Windows 8 应用程序中从生成的缓冲区播放声音,这是我尝试的 Windows Phone 8.1 解决方案,在 Visual Studio 2015 的模拟器中运行,在 VB.NET 中尝试实现 SharpDX.XAudio2。没有声音出来,但我认为它是正确的。有任何想法吗?
c++ - Windows 7 和 XAudio 2.8
我正在开发一个游戏引擎,我发现了一些困难。过去,我尝试使用 DirectX SDK(2010 年 6 月),但与 Windows 8 Kit 及其自带的 Direct 有太多冲突。我决定只使用 Windows Kit 中的 Direct3D 来制作引擎。现在,我只有一个问题:我可以开发一个只支持 XAudio 2.8 的应用程序,针对 Windows 7 的用户吗?还是我必须仅使用旧的 XAudio 2.7 支持才能做到这一点?
c++ - xAudio MasterVoice 取得进展
我最近一直在研究 xAudio,但找不到一些我需要的答案。
{不要浪费你的时间 - 我需要找到一种方法来获取主语音当前的进度}
问题是,-SourceVoice 确实提供了一种方法来给出它的状态(https://msdn.microsoft.com/en-us/library/windows/desktop/hh405047(v=vs.85).aspx)
所以,通过这个方法我们可以得到 XAUDIO2_VOICE_STATE 来计算语音播放时的当前位置。
但是使用 xAudio SourceVoice 并不是我们要使用的最终实体(或者是吗?!)。因为在到达音频设备之前,这一切都进入了 Mastering Voice。
并且 IXAudio2MasteringVoice 接口没有为我们提供像 GetState() 这样的东西。
所以我的问题是,如果我需要同步多个声音,我如何获得当前的进度。先感谢您!
c++ - 使用 ffmpeg 和 XAudio2 解码和播放音频 - 频率 raito 错误
我正在使用 ffmpeg 解码音频并使用 XAudio2 API 输出它,它使用 pts 与视频输出同步工作和播放。但它的音调很高(即听起来像花栗鼠)。
设置断点我可以看到它已经从 CreateSourceVoice 中的音频编解码器设置了正确的采样率。我难住了。
任何帮助将非常感激。
#include "DVDPlayerAudio.h"
#include "DVDDemuxUtils.h"
#include "Log.h"
#include <assert.h>
#include "DVDAudioCodecFFmpeg.h" //FIXME Move to a codec factory!!
CDVDPlayerAudio::CDVDPlayerAudio(CDVDClock* pClock) : CThread()
{
m_pClock = pClock;
m_pAudioCodec = NULL;
m_bInitializedOutputDevice = false;
m_iSourceChannels = 0;
m_audioClock = 0;
// m_currentPTSItem.pts = DVD_NOPTS_VALUE;
// m_currentPTSItem.timestamp = 0;
SetSpeed(DVD_PLAYSPEED_NORMAL);
InitializeCriticalSection(&m_critCodecSection);
m_messageQueue.SetMaxDataSize(10 * 16 * 1024);
// g_dvdPerformanceCounter.EnableAudioQueue(&m_packetQueue);
}
CDVDPlayerAudio::~CDVDPlayerAudio()
{
// g_dvdPerformanceCounter.DisableAudioQueue();
// close the stream, and don't wait for the audio to be finished
CloseStream(true);
DeleteCriticalSection(&m_critCodecSection);
}
bool CDVDPlayerAudio::OpenStream( CDemuxStreamAudio *pDemuxStream )
{
// should alway's be NULL!!!!, it will probably crash anyway when deleting m_pAudioCodec here.
if (m_pAudioCodec)
{
CLog::Log(LOGFATAL, "CDVDPlayerAudio::OpenStream() m_pAudioCodec != NULL");
return false;
}
AVCodecID codecID = pDemuxStream->codec;
CLog::Log(LOGNOTICE, "Finding audio codec for: %i", codecID);
//m_pAudioCodec = CDVDFactoryCodec::CreateAudioCodec( pDemuxStream );
m_pAudioCodec = new CDVDAudioCodecFFmpeg; //FIXME BRENT Codec Factory needed!
if (!m_pAudioCodec->Open(pDemuxStream->codec, pDemuxStream->iChannels, pDemuxStream->iSampleRate))
{
m_pAudioCodec->Dispose();
delete m_pAudioCodec;
m_pAudioCodec = NULL;
return false;
}
if( !m_pAudioCodec )
{
CLog::Log(LOGERROR, "Unsupported audio codec");
return false;
}
m_codec = pDemuxStream->codec;
m_iSourceChannels = pDemuxStream->iChannels;
m_messageQueue.Init();
CLog::Log(LOGNOTICE, "Creating audio thread");
Create();
return true;
}
void CDVDPlayerAudio::CloseStream(bool bWaitForBuffers)
{
// wait until buffers are empty
if (bWaitForBuffers) m_messageQueue.WaitUntilEmpty();
// send abort message to the audio queue
m_messageQueue.Abort();
CLog::Log(LOGNOTICE, "waiting for audio thread to exit");
// shut down the adio_decode thread and wait for it
StopThread(); // will set this->m_bStop to true
this->WaitForThreadExit(INFINITE);
// uninit queue
m_messageQueue.End();
CLog::Log(LOGNOTICE, "Deleting audio codec");
if (m_pAudioCodec)
{
m_pAudioCodec->Dispose();
delete m_pAudioCodec;
m_pAudioCodec = NULL;
}
// flush any remaining pts values
//FlushPTSQueue(); //FIXME BRENT
}
void CDVDPlayerAudio::OnStartup()
{
CThread::SetName("CDVDPlayerAudio");
pAudioPacket = NULL;
m_audioClock = 0;
audio_pkt_data = NULL;
audio_pkt_size = 0;
// g_dvdPerformanceCounter.EnableAudioDecodePerformance(ThreadHandle());
}
void CDVDPlayerAudio::Process()
{
CLog::Log(LOGNOTICE, "running thread: CDVDPlayerAudio::Process()");
int result;
// silence data
BYTE silence[1024];
memset(silence, 0, 1024);
DVDAudioFrame audioframe;
__int64 iClockDiff=0;
while (!m_bStop)
{
//Don't let anybody mess with our global variables
EnterCriticalSection(&m_critCodecSection);
result = DecodeFrame(audioframe, m_speed != DVD_PLAYSPEED_NORMAL); // blocks if no audio is available, but leaves critical section before doing so
LeaveCriticalSection(&m_critCodecSection);
if( result & DECODE_FLAG_ERROR )
{
CLog::Log(LOGERROR, "CDVDPlayerAudio::Process - Decode Error. Skipping audio frame");
continue;
}
if( result & DECODE_FLAG_ABORT )
{
CLog::Log(LOGDEBUG, "CDVDPlayerAudio::Process - Abort recieved, exiting thread");
break;
}
if( result & DECODE_FLAG_DROP ) //FIXME BRENT
{
/* //frame should be dropped. Don't let audio move ahead of the current time thou
//we need to be able to start playing at any time
//when playing backwords, we try to keep as small buffers as possible
// set the time at this delay
AddPTSQueue(audioframe.pts, m_dvdAudio.GetDelay());
*/
if (m_speed > 0)
{
__int64 timestamp = m_pClock->GetAbsoluteClock() + (audioframe.duration * DVD_PLAYSPEED_NORMAL) / m_speed;
while( !m_bStop && timestamp > m_pClock->GetAbsoluteClock() ) Sleep(1);
}
continue;
}
if( audioframe.size > 0 )
{
// we have succesfully decoded an audio frame, openup the audio device if not already done
if (!m_bInitializedOutputDevice)
{
m_bInitializedOutputDevice = InitializeOutputDevice();
}
//Add any packets play
m_dvdAudio.AddPackets(audioframe.data, audioframe.size);
// store the delay for this pts value so we can calculate the current playing
//AddPTSQueue(audioframe.pts, m_dvdAudio.GetDelay() - audioframe.duration);//BRENT
}
// if we where asked to resync on this packet, do so here
if( result & DECODE_FLAG_RESYNC )
{
CLog::Log(LOGDEBUG, "CDVDPlayerAudio::Process - Resync recieved.");
//while (!m_bStop && (unsigned int)m_dvdAudio.GetDelay() > audioframe.duration ) Sleep(5); //BRENT
m_pClock->Discontinuity(CLOCK_DISC_NORMAL, audioframe.pts);
}
#ifdef USEOLDSYNC
//Clock should be calculated after packets have been added as m_audioClock points to the
//time after they have been played
const __int64 iCurrDiff = (m_audioClock - m_dvdAudio.GetDelay()) - m_pClock->GetClock();
const __int64 iAvDiff = (iClockDiff + iCurrDiff)/2;
//Check for discontinuity in the stream, use a moving average to
//eliminate highfreq fluctuations of large packet sizes
if( ABS(iAvDiff) > 5000 ) // sync clock if average diff is bigger than 5 msec
{
//Wait untill only the new audio frame wich triggered the discontinuity is left
//then set disc state
while (!m_bStop && (unsigned int)m_dvdAudio.GetBytesInBuffer() > audioframe.size ) Sleep(5);
m_pClock->Discontinuity(CLOCK_DISC_NORMAL, m_audioClock - m_dvdAudio.GetDelay());
CLog::("CDVDPlayer:: Detected Audio Discontinuity, syncing clock. diff was: %I64d, %I64d, av: %I64d", iClockDiff, iCurrDiff, iAvDiff);
iClockDiff = 0;
}
else
{
//Do gradual adjustments (not working yet)
//m_pClock->AdjustSpeedToMatch(iClock + iAvDiff);
iClockDiff = iCurrDiff;
}
#endif
}
}
void CDVDPlayerAudio::OnExit()
{
//g_dvdPerformanceCounter.DisableAudioDecodePerformance();
// destroy audio device
CLog::Log(LOGNOTICE, "Closing audio device");
m_dvdAudio.Destroy();
m_bInitializedOutputDevice = false;
CLog::Log(LOGNOTICE, "thread end: CDVDPlayerAudio::OnExit()");
}
// decode one audio frame and returns its uncompressed size
int CDVDPlayerAudio::DecodeFrame(DVDAudioFrame &audioframe, bool bDropPacket)
{
CDVDDemux::DemuxPacket* pPacket = pAudioPacket;
int n=48000*2*16/8, len;
//Store amount left at this point, and what last pts was
unsigned __int64 first_pkt_pts = 0;
int first_pkt_size = 0;
int first_pkt_used = 0;
int result = 0;
// make sure the sent frame is clean
memset(&audioframe, 0, sizeof(DVDAudioFrame));
if (pPacket)
{
first_pkt_pts = pPacket->pts;
first_pkt_size = pPacket->iSize;
first_pkt_used = first_pkt_size - audio_pkt_size;
}
for (;;)
{
/* NOTE: the audio packet can contain several frames */
while (audio_pkt_size > 0)
{
len = m_pAudioCodec->Decode(audio_pkt_data, audio_pkt_size);
if (len < 0)
{
/* if error, we skip the frame */
audio_pkt_size=0;
m_pAudioCodec->Reset();
break;
}
// fix for fucked up decoders //FIXME BRENT
if( len > audio_pkt_size )
{
CLog::Log(LOGERROR, "CDVDPlayerAudio:DecodeFrame - Codec tried to consume more data than available. Potential memory corruption");
audio_pkt_size=0;
m_pAudioCodec->Reset();
assert(0);
}
// get decoded data and the size of it
audioframe.size = m_pAudioCodec->GetData(&audioframe.data);
audio_pkt_data += len;
audio_pkt_size -= len;
if (audioframe.size <= 0) continue;
audioframe.pts = m_audioClock;
// compute duration.
n = m_pAudioCodec->GetChannels() * m_pAudioCodec->GetBitsPerSample() / 8 * m_pAudioCodec->GetSampleRate();
if (n > 0)
{
// safety check, if channels == 0, n will result in 0, and that will result in a nice devide exception
audioframe.duration = (unsigned int)(((__int64)audioframe.size * DVD_TIME_BASE) / n);
// increase audioclock to after the packet
m_audioClock += audioframe.duration;
}
//If we are asked to drop this packet, return a size of zero. then it won't be played
//we currently still decode the audio.. this is needed since we still need to know it's
//duration to make sure clock is updated correctly.
if( bDropPacket )
{
result |= DECODE_FLAG_DROP;
}
return result;
}
// free the current packet
if (pPacket)
{
CDVDDemuxUtils::FreeDemuxPacket(pPacket); //BRENT FIXME
pPacket = NULL;
pAudioPacket = NULL;
}
if (m_messageQueue.RecievedAbortRequest()) return DECODE_FLAG_ABORT;
// read next packet and return -1 on error
LeaveCriticalSection(&m_critCodecSection); //Leave here as this might stall a while
CDVDMsg* pMsg;
MsgQueueReturnCode ret = m_messageQueue.Get(&pMsg, INFINITE);
EnterCriticalSection(&m_critCodecSection);
if (MSGQ_IS_ERROR(ret) || ret == MSGQ_ABORT) return DECODE_FLAG_ABORT;
if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET))
{
CDVDMsgDemuxerPacket* pMsgDemuxerPacket = (CDVDMsgDemuxerPacket*)pMsg;
pPacket = pMsgDemuxerPacket->GetPacket();
pMsgDemuxerPacket->m_pPacket = NULL; // XXX, test
pAudioPacket = pPacket;
audio_pkt_data = pPacket->pData;
audio_pkt_size = pPacket->iSize;
}
else
{
// other data is not used here, free if
// msg itself will still be available
pMsg->Release();
}
// if update the audio clock with the pts
if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET) || pMsg->IsType(CDVDMsg::GENERAL_RESYNC))
{
if (pMsg->IsType(CDVDMsg::GENERAL_RESYNC))
{
//player asked us to sync on this package
CDVDMsgGeneralResync* pMsgGeneralResync = (CDVDMsgGeneralResync*)pMsg;
result |= DECODE_FLAG_RESYNC;
m_audioClock = pMsgGeneralResync->GetPts();
}
else if (pPacket->pts != DVD_NOPTS_VALUE) // CDVDMsg::DEMUXER_PACKET, pPacket is already set above
{
if (first_pkt_size == 0)
{
//first package
m_audioClock = pPacket->pts;
}
else if (first_pkt_pts > pPacket->pts)
{
//okey first packet in this continous stream, make sure we use the time here
m_audioClock = pPacket->pts;
}
else if((unsigned __int64)m_audioClock < pPacket->pts || (unsigned __int64)m_audioClock > pPacket->pts)
{
//crap, moved outsided correct pts
//Use pts from current packet, untill we find a better value for it.
//Should be ok after a couple of frames, as soon as it starts clean on a packet
m_audioClock = pPacket->pts;
}
else if(first_pkt_size == first_pkt_used)
{
//Nice starting up freshly on the start of a packet, use pts from it
m_audioClock = pPacket->pts;
}
}
}
pMsg->Release();
}
}
void CDVDPlayerAudio::SetSpeed(int speed)
{
m_speed = speed;
//if (m_speed == DVD_PLAYSPEED_PAUSE) m_dvdAudio.Pause(); //BRENT FIXME
//else m_dvdAudio.Resume();
}
bool CDVDPlayerAudio::InitializeOutputDevice()
{
int iChannels = m_pAudioCodec->GetChannels();
int iSampleRate = m_pAudioCodec->GetSampleRate();
int iBitsPerSample = m_pAudioCodec->GetBitsPerSample();
//bool bPasstrough = m_pAudioCodec->NeedPasstrough(); //BRENT
if (iChannels == 0 || iSampleRate == 0 || iBitsPerSample == 0)
{
CLog::Log(LOGERROR, "Unable to create audio device, (iChannels == 0 || iSampleRate == 0 || iBitsPerSample == 0)");
return false;
}
CLog::Log(LOGNOTICE, "Creating audio device with codec id: %i, channels: %i, sample rate: %i", m_codec, iChannels, iSampleRate);
if (m_dvdAudio.Create(iChannels, iSampleRate, iBitsPerSample, /*bPasstrough*/0)) // always 16 bit with ffmpeg ? //BRENT Passthrough needed?
{
return true;
}
CLog::Log(LOGERROR, "Failed Creating audio device with codec id: %i, channels: %i, sample rate: %i", m_codec, iChannels, iSampleRate);
return false;
}
c# - XAudio2 与 C#
我希望用 XAudio2 替换我的 32 位 DirectSound 音频 API。XAudio2 是否适用于 64 位 C# 应用程序?如果是这样,我不完全确定如何设置项目以开始使用 XAudio2。我在网上看到的所有示例都是针对 C++ 的。
c# - 如何在 UWP 应用程序上播放原始 pcm 音频字节?
我有一个通用 Windows 平台 (UWP) 应用程序,我想在其中播放我在旧的 Window phone 8.1 应用程序上录制的音频字节。
音频是带有原始 PCM 音频(单声道、16 位、16kHz)的字节数组。
在我的旧 Windows phone 8.1 应用程序上,我只需使用 3 行代码即可。
不幸的是,UWP 中没有“SoundEffect”。
在 C# UWP 应用程序中是否有一种简单的方法可以做到这一点?
用于测试目的的音频样本(单声道、16 位、16000Hz、小端)
PS:我查看了 Wasapi,但它全部使用 c++,并且找不到通常在 c# 中工作的人的简单示例
openal - XAudio2 是否有最大声音数?
一段时间前,我们开始将声音引擎迁移到 XAudio2,但还没有完成。目前我们仍在使用 OpenAL,并且遇到了一个问题,即“源”的最大数量(我相信在 XAudio2 中被称为“声音”)取决于您的硬件。
我们可以升级我们的 OpenAL 东西以回收资源,但如果 XAudio2 为我们解决了这个问题,那么我宁愿专注于完成迁移。
我无法找到有关此的任何信息,也没有看到人们在使用 XAudio2 解决此问题的任何帖子......所以我猜没有限制?
c++ - 一起使用 xaudio2 和一个并口
我在我的研究实验室中使用 C++ 编写神经科学实验。我们正在研究触觉感知,我们使用并行端口来触发我们的大脑刺激设备。时机非常重要。我们最近开始使用 xaudio2 播放非常简单的 WAV 文件,这些文件用于触发我们的振动触觉刺激器(例如,我们的“触觉”刺激是 100 和 200 Hz 的声音,持续时间为 100 ms,它移动压电刺激器放在手上)。我们的问题是,我们需要通过并行端口向大脑刺激器发送 3 个命令:在触觉刺激前 40 毫秒一次,在刺激开始后 10 毫秒一次,在刺激开始后 60 毫秒第三次。请记住,触觉刺激持续 100 毫秒。但是,xaudio2 触发声音的方式是它播放波形并阻塞直到完成。结果,程序忽略了应该在激励期间发送的两个并行端口命令。有谁知道我如何确保在整个 100 毫秒的持续时间内仍然触发触觉刺激,而且在此期间还发送并行端口命令?我使用 MSDN XAudio2Samples 作为播放 wav 文件的基本结构,而 PlayWave 功能是在播放 Wav 文件时“阻止”任何其他输入的功能 - 但我不知道如何修改它所以在播放声音时,它还将接受我的并行端口命令(即 Out32(888,1))。谢谢!有谁知道我如何确保在整个 100 毫秒的持续时间内仍然触发触觉刺激,而且在此期间还发送并行端口命令?我使用 MSDN XAudio2Samples 作为播放 wav 文件的基本结构,而 PlayWave 功能是在播放 Wav 文件时“阻止”任何其他输入的功能 - 但我不知道如何修改它所以在播放声音时,它还将接受我的并行端口命令(即 Out32(888,1))。谢谢!有谁知道我如何确保在整个 100 毫秒的持续时间内仍然触发触觉刺激,而且在此期间还发送并行端口命令?我使用 MSDN XAudio2Samples 作为播放 wav 文件的基本结构,而 PlayWave 功能是在播放 Wav 文件时“阻止”任何其他输入的功能 - 但我不知道如何修改它所以在播放声音时,它还将接受我的并行端口命令(即 Out32(888,1))。谢谢!t 弄清楚如何修改它,以便在播放声音时它也会接受我的并行端口命令(即 Out32(888,1))。谢谢!t 弄清楚如何修改它,以便在播放声音时它也会接受我的并行端口命令(即 Out32(888,1))。谢谢!
这是 PlayWave 函数的代码:
c#-4.0 - XAudio2 Source/Master Voice SetVolume 参数
我正在尝试为我的 WPF 应用程序构建一个音量滑块,以应用于我通过 XAudio2 输出的 WAV 文件。
我把所有东西都串起来了,可以播放声音。伟大的!
我只是无法理解 SetVolume 方法的参数。
谁能解释一下音量滑块的合适值是多少?
我确定我遗漏了一些非常明显的东西,而且我只是不习惯播放音频文件,所以我对启动毫无头绪。
我希望我真的想要两个滑块,一个用于主控声音,一个用于源声音。