小编And*_*ell的帖子

Android SoundPool有多糟糕?还有什么替代品?

我在将Android SoundPool视为一种在我的通用游戏开发库中实现声音效果的机制.这看起来很理想.

但是,一点点研究表明,有所有 种类的 错误SoundPool.这些错误SoundPool仍然相关吗?

因为我正在开发一个库,任何错误都会SoundPool成为我库中的错误,我希望将我的用户与此隔离开来.

所以我的问题基本上是:我应该将什么API用于音频?

使用AudioTrack和编写我自己的混音器并非不可能.但显然最好避免这样做.是否有任何API为我提供解码?

我需要能够播放合理数量的同步音效(至少16个,比方说),并且更加开放.听起来需要以低延迟开始播放.WAV需要支持文件(MP3/Ogg不重要).音效需要支持无缝循环和动态,单独的音量调节.需要正确支持Android应用生命周期.

我听说有一个1MB的限制SoundPool,这可能是每个单独的声音效果可接受,但不适用于所有缓冲/声音.有人能告诉我确切的限制是什么吗?

最后,我需要能够以压缩格式播放背景音乐,并且CPU负载较低.我认为这MediaPlayer是理想的.它可以与其他API并行使用吗?

我知道有几个人一直在MediaPlayer用来填补SoundPool.但它是否支持我需要的功能?

我错过了其他任何音频API吗?

audio android soundpool

76
推荐指数
2
解决办法
2万
查看次数

在讨论编程语言时,"强大"意味着什么?

在编程语言讨论/比较的背景下,术语"权力"是什么意思?

它有明确的含义吗?即使定义不明确?

如果有人说"语言X比语言Y更强大"或者问一个问题,它们是什么意思 - 或者他们试图找出什么信息?

programming-languages

27
推荐指数
5
解决办法
6398
查看次数

在没有AppDomains的情况下运行时重新编译C#

假设我有两个C#应用程序 - game.exe(XNA,需要支持Xbox 360)和editor.exe(在WinForms中托管的XNA) - 它们共享一个engine.dll可以完成绝大部分工作的程序集.

现在让我们说我想添加一些基于C#的脚本(它不是"脚本",但我会称之为).每个级别都有自己继承自基类的类(我们称之为LevelController).

这些是这些脚本的重要约束:

  1. 它们需要是真实的,编译好的C#代码

  2. 他们应该需要最少的手动"粘合"工作,如果有的话

  3. 它们必须与其他所有内容在同一个AppDomain中运行

对于游戏 - 这非常简单:所有脚本类都可以编译成一个程序集(比如说levels.dll),并且可以根据需要使用反射来实例化各个类.

编辑要困难得多.编辑器能够在编辑器窗口中"玩游戏",然后将所有内容重置回原来的位置(这就是编辑器首先需要了解这些脚本的原因).

我想要实现的基本上是编辑器中的"重新加载脚本"按钮,它将重新编译并加载与正在编辑的级别相关联的脚本类,当用户按下"播放"按钮时,创建最近的实例编译脚本.

其结果将是编辑器中的快速编辑测试工作流程(而不是替代方案 - 保存级别,关闭编辑器,重新编译解决方案,启动编辑器,加载级别,测试).


现在我我已经找到了实现这个目标的潜在方法 - 这本身就会产生一些问题(如下所示):

  1. .cs将给定级别(或者,如果需要,整个levels.dll项目)所需的文件集合编译为临时的,唯一命名的程序集.那个集会需要参考engine.dll.如何在运行时以这种方式调用编译器?如何让它输出这样的程序集(我可以在内存中执行)吗?

  2. 加载新装配.我在同一个进程中加载​​具有相同名称的类是否重要?(我的印象是名称是由程序集名称限定的?)

    现在,正如我所提到的,我无法使用AppDomains.但是,另一方面,我不介意泄漏旧版本的脚本类,因此卸载的能力并不重要.除非是吗?我假设加载可能几百个组件是可行的.

  3. 在播放关卡时,实例是从刚加载的特定程序集继承自LevelController的类.这该怎么做?

最后:

这是一种明智的做法吗?它可以做得更好吗?


更新:这些天我使用一种更简单的方法来解决潜在的问题.

c# compilation assembly.load

20
推荐指数
1
解决办法
6341
查看次数

为什么标准C#事件调用模式是线程安全的,没有内存屏障或缓存失效?类似的代码怎么样?

在C#中,这是以线程安全方式调用事件的标准代码:

var handler = SomethingHappened;
if(handler != null)
    handler(this, e);
Run Code Online (Sandbox Code Playgroud)

其中,可能在另一个线程上,编译器生成的add方法用于Delegate.Combine创建新的多播委托实例,然后在编译器生成的字段上设置该实例(使用互锁比较交换).

(注意:出于这个问题的目的,我们不关心在事件订阅者中运行的代码.假设它在删除时是线程安全且健壮的.)


在我自己的代码中,我想按照以下方式做类似的事情:

var localFoo = this.memberFoo;
if(localFoo != null)
    localFoo.Bar(localFoo.baz);
Run Code Online (Sandbox Code Playgroud)

哪里this.memberFoo可以由另一个线程设置.(这只是一个线程,所以我不认为它需要联锁 - 但也许这里有副作用?)

(并且,显然,假设它Foo是"不可变的",我们在这个线程上使用它时不会主动修改它.)


现在我理解这是线程安全的明显原因:从引用字段读取是原子的.复制到本地可确保我们不会获得两个不同的值.(显然只能从.NET 2.0保证,但我认为它在任何理智的.NET实现中都是安全的吗?)


但我不明白的是:被引用的对象实例所占用的内存如何?特别是在缓存一致性方面?如果"writer"线程在一个CPU上执行此操作:

thing.memberFoo = new Foo(1234);
Run Code Online (Sandbox Code Playgroud)

什么保证Foo分配新内存的内存不会出现在"读取器"运行的CPU的缓存中,具有未初始化的值?什么确保localFoo.baz(上面)不读取垃圾?(跨平台的保证有多好?在Mono上?在ARM上?)

如果新创建的foo恰好来自游泳池呢?

thing.memberFoo = FooPool.Get().Reset(1234);
Run Code Online (Sandbox Code Playgroud)

从内存的角度来看,这似乎没有什么不同,只是一个新的分配 - 但是.NET分配器可能会让第一个案例有效吗?


在我提出这个问题时,我的想法是需要一个内存屏障来确保 - 不是因为读取依赖而不能移动内存访问 - 而是作为CPU的一个信号来清除任何缓存失效.

我的来源是维基百科,所以你要做的就是这样.

(我可能会猜测,也许在连动比较交换作家线程上无效缓存读者?或者,也许所有的读取原因失效吗?或者指针引用引起失效?我特别关注如何平台特有的这些东西的声音.)


更新:只是为了更明确地说明问题是关于CPU缓存失效以及.NET提供的保证(以及这些保证可能如何依赖于CPU架构):

  • 假设我们在字段Q(内存位置)中存储了引用.
  • 上CPU (作家)我们在初始化存储器位置的对象R …

c# memory-model thread-safety memory-barriers mesi

15
推荐指数
1
解决办法
667
查看次数

将子进程的输出(stdout,stderr)重定向到Visual Studio中的"输出"窗口

目前我正从我的C#程序启动批处理文件:

System.Diagnostics.Process.Start(@"DoSomeStuff.bat");
Run Code Online (Sandbox Code Playgroud)

我希望能够做的是将该子进程的输出(stdout和stderr)重定向到Visual Studio中的Output窗口(特别是Visual C#Express 2008).

有没有办法做到这一点?

(另外:这样就不会全部缓冲,然后在子进程完成时吐出到Output窗口.)


(顺便说一句:目前我可以通过使我的程序成为"Windows应用程序"而不是"控制台应用程序"来使进程的stdout(但不是stderr)出现在"输出"窗口中.如果程序运行,这会中断在Visual Studio之外,但在我的特定情况下这是好的.)

c# stdout visual-studio-2008 visual-studio output-window

14
推荐指数
2
解决办法
2万
查看次数

创建n*m值的所有组合

假设我有这样的数据结构IEnumerable<IEnumerable<object>>:

{
    { A, B }
    { 1, 2, 3 }
    { Z }
}
Run Code Online (Sandbox Code Playgroud)

外部数组可以包含任意数量的内部数组.并且内部数组可以各自独立地包含任意数量的元素.并且为了简单起见,假设没有数组是空的.

我想把它变成IEnumerable<IEnumerable<object>>这样的:

{ { A, 1, Z }, { A, 2, Z }, { A, 3, Z }, { B, 1, Z }, { B, 2, Z }, { B, 3, Z } }
Run Code Online (Sandbox Code Playgroud)

其中包含原始结构中值的每个组合.因此,每个内部数组中的每个元素都通过索引映射到原始外部数组中的元素/数组.

在C#中最简单的方法是什么?

c# linq

13
推荐指数
1
解决办法
2011
查看次数

如何在非托管内存中实例化C#类?(可能?)

更新:现在有一个被接受的答案"有效".你应该永远,永远,永远,永远使用它.曾经.


首先让我先说明我是一名游戏开发者.想要这样做有一个合法的 - 如果非常不寻常 - 与性能相关的原因.


假设我有一个像这样的C#类:

class Foo
{
    public int a, b, c;
    public void MyMethod(int d) { a = d; b = d; c = a + b; }
}
Run Code Online (Sandbox Code Playgroud)

没有什么花哨.请注意,它是仅包含值类型的引用类型.

在托管代码中,我希望有这样的东西:

Foo foo;
foo = Voodoo.NewInUnmanagedMemory<Foo>(); // <- ???
foo.MyMethod(1);
Run Code Online (Sandbox Code Playgroud)

这个功能NewInUnmanagedMemory会是什么样的?如果无法在C#中完成,可以在IL中完成吗?(或者可能是C++/CLI?)

基本上:有没有办法 - 无论多么苛刻 - 将一些完全任意的指针转换为对象引用.并且 - 没有使CLR爆炸 - 该死的后果.

(提出问题的另一种方法是:"我想为C#实现自定义分配器")

这导致了后续问题:当面对指向托管内存之外的引用时,垃圾收集器会做什么(特定于实现,如果需要)?

并且,与此相关,如果Foo将引用作为成员字段会发生什么?如果它指向托管内存怎么办?如果它只指向非托管内存中分配的其他对象怎么办?

最后,如果这是不可能的:为什么?


更新:到目前为止,这是"缺失的部分":

#1:如何将IntPtr对象转换为对象引用?虽然无法验证的IL可能是可能的(见评论).到目前为止,我没有运气.该框架似乎非常小心,以防止这种情况发生.

(能够在运行时获取非blittable托管类型的大小和布局信息也很好.同样,框架试图使这变得不可能.)

#2:假设问题可以解决 - 当GC遇到指向GC堆外部的对象引用时,它会做什么?它崩溃了吗?Anton Tykhyy 在他的回答中猜测它会.考虑到框架对于防止#1的谨慎程度,它似乎很可能.确认这一点的东西会很好. …

.net c# clr garbage-collection unmanaged-memory

12
推荐指数
3
解决办法
4354
查看次数

编写决策代码的更优雅的方法是评估具有不同优先级的多个输入?

我正在为游戏编写一些决策AI,我已经提出了以下代码.

if(pushedLeft && leftFree && leftExists)
    GoLeft();
else if(pushedRight && rightFree && rightExists)
    GoRight();
else if(leftFree && leftExists)
    GoLeft();
else if(rightFree && rightExists)
    GoRight();
else if(pushedLeft && leftExists)
    GoLeft();
else if(pushedRight && rightExists)
    GoRight();
else if(leftExists)
    GoLeft();
else if(rightExists)
    GoRight();
// else do nothing...
Run Code Online (Sandbox Code Playgroud)

这是一个相当长的if语句流,具有类似的条件!

请注意,它使这个很好的模式:

L1 L2 L3  -> L
R1 R2 R3  -> R
   L2 L3  -> L
   R2 R3  -> R
L1    L3  -> L
R1    R3  -> R
      L3  -> L
      R3  -> R …
Run Code Online (Sandbox Code Playgroud)

c# design-patterns if-statement

12
推荐指数
2
解决办法
2810
查看次数

MSBuild:如何在构建时创建和使用任务来转换内容项?

我有一个类似这样的Silverlight 3项目:

<ItemGroup>
  <Content Include="Content\image1.png">
  </Content>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

基本上我已经将PNG文件添加到我的项目中,并将其构建操作设置为"内容".这很好用.

现在我想做的是能够以不同的格式将图像添加到我的项目中,并在构建时将它们转换为PNG - 这样最终结果就好像我已经将PNG图像添加到项目中一样(作为内容)首先.

换句话说 - 我希望图像以PNG格式显示在我的XAP包中.

理想情况下,我希望这样做,它将与Visual Web Developer 2008 Express一起使用(因此我可以通过将图像文件拖入IDE并可能更改其构建操作来将图像文件添加到我的项目中),而无需制作任何系统全面的变化.

我想要转换的特定格式是XCF - 我已经有.NET代码来转换为PNG.我假设我必须创建一个MSBuild任务.

我没有太多的MSBuild经验,我想知道如何把这样的东西放在一起.


基于我对MSBuild如何工作的粗略理解,我认为我需要知道:

  • 如何@(Content)根据文件扩展名(重新)从(或其他)集合中移动它们来创建项目集合?
    • 或者:创建我可以在Visual Web Developer 2008 Express中使用的自定义构建操作
  • 如何接收输入项的路径Task
  • 哪里(.NET或MSBuild?)和如何指定生成的输出文件的位置Task
  • 如果文件的输入文件发生变化,如何确保重建文件?
  • 在哪里(可能BeforeBuild?)以及如何将转换后的项目重新注入@(Content)?(或者我应该使用其他一些系列?)
    • 或者:将其纳入XAP的其他方式?

如果这似乎是一种合理的做事方式,或者我错过了什么?

msbuild silverlight msbuild-task visual-studio

7
推荐指数
1
解决办法
2436
查看次数

.NET JIT是否会内联一个调用另一个小函数的小函数?

我想知道 - .NET JITter会递归内联从其他小函数调用的内联函数吗?

仅举例如:

public static float Square(float value)
{
    return value * value;
}

public static float Cube(float value)
{
    return Square(value) * value;
}
Run Code Online (Sandbox Code Playgroud)

如果我Cube从某个地方打电话,它会一直内联,还是最终会调用函数Square

而且,如果是这样的话,它会有多深才能进行内联?(说我疯狂到以同样的方式实现QuarticQuintic功能.)

.net jit inlining

6
推荐指数
1
解决办法
684
查看次数