惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Securelist
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
V
V2EX
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
The Register - Security
The Register - Security
Recorded Future
Recorded Future
Y
Y Combinator Blog
小众软件
小众软件
Jina AI
Jina AI
V2EX - 技术
V2EX - 技术
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
宝玉的分享
宝玉的分享
The Hacker News
The Hacker News
C
Cybersecurity and Infrastructure Security Agency CISA
K
Kaspersky official blog
博客园 - 三生石上(FineUI控件)
T
Threatpost
博客园 - 聂微东
Scott Helme
Scott Helme
IT之家
IT之家
N
Netflix TechBlog - Medium
T
The Exploit Database - CXSecurity.com
S
Schneier on Security
MongoDB | Blog
MongoDB | Blog
T
Tor Project blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
A
About on SuperTechFans
酷 壳 – CoolShell
酷 壳 – CoolShell
C
CERT Recently Published Vulnerability Notes
P
Palo Alto Networks Blog
Spread Privacy
Spread Privacy
C
Check Point Blog
L
LINUX DO - 最新话题
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Last Week in AI
Last Week in AI
Attack and Defense Labs
Attack and Defense Labs
T
Tailwind CSS Blog
罗磊的独立博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Webroot Blog
Webroot Blog
Help Net Security
Help Net Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
爱范儿
爱范儿
PCI Perspectives
PCI Perspectives
Security Latest
Security Latest

博客园 - 吴文力

VC 开机自动启动程序代码 Symbian中音频API的使用(摘录) symbian 游戏开发中一些技术细节(摘录) 动态库的调用等技术 VC小技巧 15个问题 - 吴文力 - 博客园 VC 常见问题百问 VC/MFC Q&A 200409 DELL 电脑的区别 报表式CListCtrl的使用详解初稿 俄罗斯科学家语出惊人:怀孕前就能预设生男生女 PE文件格式详解 怎样在目录中寻找文件 如何让程序自动管理线程 WinNT & Win2K下实现进程的完全隐藏——宿主程序 木马病毒是如何利用文件关联和设置名感染的 104种清除木马完全攻略 Programming Applications for Microsoft Windows(四) Programming Applications for Microsoft Windows(三) Programming Applications for Microsoft Windows(二)
Symbian中声音处理
吴文力 · 2009-08-16 · via 博客园 - 吴文力

引擎中使用CMdaAudioOutputStream和MMdaAudioOutputStreamCallback完成声音播放功能。它主要有三个类组成:
  CAudioStreamPlayer。它复合CMdaAudioOutputStream,继承CActive,实现MMdaAudioOutputStreamCallback接口。我们需要小心的维持缓冲区的大小以获得低延迟播放。CActive不断的建立新的任务,在RunL函数中估算缓冲区中的剩余数据,向其中追加适当的数据,维持缓冲区的预期大小。
  CSimpleMixer。它实现CAudioGenerator接口。因为CMdaAudioOutputStream是一个单一的流式播放器,所以需要写一个混音器进行波形混合。这里波形混合就是简单的数据相加。混音器有许多的声道(channel)。每个channel记录了其中的CAudio指针和当前播放位置。
  CAudio。包含一个音频缓冲区。对每个声音文件,我们还需要一个类把它载入到内存缓冲区中。
        我不会在此讲解如何实现音频播放,那需要单独的一篇文章。如果你也使用这种方法实现声音播放,我只想在此和大家讨论两个问题。
需要学习声音基础的话,可以参考www.newlc.com/article.php?id_article=113。(可惜我当时学习声音时那篇文章和代码找不到了)

1.5.1. 声音的关闭和开启
        因为整个音频系统是一个拉的结构,音频流从混音器那里拉数据,混音器从音频缓冲区中拉数据。所以,只要把CMdaAudioOutputStream和写数据的CActive对象delete掉,声音播放就全部停止了。在我的实现中,也就是delete CAudioStreamPlayer对象即可。再想要开启声音,只需要重新创建这个对象。
这个实现的好处是程序的其它部分不需要保存声音是否开启这个状态。因为CAudio和CSimpleMixer对象是存在的,CAudio就可以把自己插入到Mixer的channel中,觉得自己好像在播放一样。其实因为CAudioStreamPlayer根本没有从Mixer向外拉数据,声音设备是完全停止的。
        但是在恢复声音播放时有一点需要注意,恢复前需要清空混音器中的声音数据。因为经过了长时间的运行,混音器中的各个channel中已经塞满了各种声音。如果此时突然打开,会传出各种延迟了的杂音。

1.5.2. 特殊错误处理
        MMdaAudioOutputStreamCallback接口中的几个回调函数MaoscOpenComplete、MaoscBufferCopied和MaoscPlayComplete都有一个错误码参数。你不能忽略这个参数。
比如MaoscPlayComplete函数,是在音频停止播放时被调用。停止播放的原因可能是多种多样的。我们都知道要处理KErrUnderflow这个情况,这个错误吗意味着混音器没有及时的供给它音频数据。此时需要重新启动声音流。但是还有一些情况比如KErrDied和KErrInUse很容易被忽略。KErrDied发生在接听电话时,此时声音线程已经死了,那么就需要重建整个音频系统。KErrInUse发生在收到短信时,此时声音设备被抢占,用来播放短信提示音。此时你也需要重建整个声音系统,但是此时不能立刻重建,否则还是一样的结果。你应该等待几秒钟之后才重建它。
上面说的重启声音流和重建声音系统深度不同。重启声音流在稍后的代码中可以看到。其中RunAudioL向音频流写入了第一个声音缓冲区。重建声音系统在我的实现中就是指先delete 再NewL创建CAudioStreamPlayer对象。
这三个错误的处理代码如下:
// Audio stream API callback: Called when playback has finished.
void CAudioStreamPlayer::MaoscPlayComplete(TInt anError) 
{
 if (m_bInDelay)
  return;
 // If we finish due to an underflow, we"ll need to restart playback.
 // Normally KErrUnderlow is raised at stream end, but in our case the API
 // should never see the stream end -- we are continuously feeding it more
 // data! Many underflow errors mean that the latency target is too low.
 if ( anError == KErrUnderflow ) {
  iObserver->MasoMessage(_L("Play Underflow"));
  // The number of samples played gets resetted to zero when we restart
  // playback after underflow
  iBaseSamplesPlayed = iSamplesWritten;

  // Stop and restart
  iStream->Stop();
  Cancel();
#ifdef RATE_16K
  iStream->SetAudioPropertiesL(TMdaAudioDataSettings::ESampleRate16000Hz, 
          TMdaAudioDataSettings::EChannelsMono);
#else
  iStream->SetAudioPropertiesL(TMdaAudioDataSettings::ESampleRate8000Hz, 
          TMdaAudioDataSettings::EChannelsMono);
#endif
  iStream->SetVolume(iStream->MaxVolume() / 4);
  TRAPD(error, RunAudioL());
  if ( error != KErrNone ) {
   User::Panic(KPlay, error);
  }

  return;      
 } 
 else if ( anError == KErrDied )
 {
  m_bInDelay = ETrue;
  m_RebuildDelay = 0; // no delay
 }
 else if ( anError == KErrInUse )
 {
  m_bInDelay = ETrue;
  m_RebuildDelay = 3000; // delay 3 second
 }
 else if ( anError != KErrNone ) {
  // Some other error, panic!
  User::Panic(KPlayComplete, anError);
 }
}
        由外界发现m_RebuildDelay标志,重建CAduioStreamPlayer这个对象。
除了MaoscPlayComplete,我在MaoscBufferCopied中忽略了KErrUnderflow和KErrAbort错误。在MaoscBufferCopied和MaoscOpenComplete也处理了KErrInUse错误。
经过上面的处理,我的程序已经可以安全的应对来电、短信、切换程序等特殊情况了。