问题标签 [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.

0 投票
2 回答
131 浏览

vb.net - 在 Windows Phone 8.1 应用程序中生成音调或声音

我正在尝试在 Windows Phone 8.1 上以设定的频率和持续时间生成音调。跟进此处介绍的主题:在 Windows 8 应用程序中从生成的缓冲区播放声音,这是我尝试的 Windows Phone 8.1 解决方案,在 Visual Studio 2015 的模拟器中运行,在 VB.NET 中尝试实现 SharpDX.XAudio2。没有声音出来,但我认为它是正确的。有任何想法吗?

0 投票
1 回答
833 浏览

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 支持才能做到这一点?

0 投票
1 回答
150 浏览

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() 这样的东西。

所以我的问题是,如果我需要同步多个声音,我如何获得当前的进度。先感谢您!

0 投票
0 回答
639 浏览

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; }
0 投票
1 回答
1684 浏览

c# - XAudio2 与 C#

我希望用 XAudio2 替换我的 32 位 DirectSound 音频 API。XAudio2 是否适用于 64 位 C# 应用程序?如果是这样,我不完全确定如何设置项目以开始使用 XAudio2。我在网上看到的所有示例都是针对 C++ 的。

0 投票
2 回答
1794 浏览

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# 中工作的人的简单示例

0 投票
1 回答
543 浏览

openal - XAudio2 是否有最大声音数?

一段时间前,我们开始将声音引擎迁移到 XAudio2,但还没有完成。目前我们仍在使用 OpenAL,并且遇到了一个问题,即“源”的最大数量(我相信在 XAudio2 中被称为“声音”)取决于您的硬件。

我们可以升级我们的 OpenAL 东西以回收资源,但如果 XAudio2 为我们解决了这个问题,那么我宁愿专注于完成迁移。

我无法找到有关此的任何信息,也没有看到人们在使用 XAudio2 解决此问题的任何帖子......所以我猜没有限制?

0 投票
0 回答
97 浏览

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 函数的代码:

0 投票
1 回答
573 浏览

c#-4.0 - XAudio2 Source/Master Voice SetVolume 参数

我正在尝试为我的 WPF 应用程序构建一个音量滑块,以应用于我通过 XAudio2 输出的 WAV 文件。

我把所有东西都串起来了,可以播放声音。伟大的!

我只是无法理解 SetVolume 方法的参数。

谁能解释一下音量滑块的合适值是多少?

我确定我遗漏了一些非常明显的东西,而且我只是不习惯播放音频文件,所以我对启动毫无头绪。

我希望我真的想要两个滑块,一个用于主控声音,一个用于源声音。

0 投票
0 回答
128 浏览

c# - C# 音频设备枚举和静音

由于DirectSound已弃用和XAudio2删除枚举,C# 应用程序在 Windows 7 及更高版本上枚举和修改音频设备的“正确”方法是什么?

我见过使用NAudioCSCore或其他库和包装器的解决方案。C# 有裸机解决方案吗?