【问题标题】:Map AudioClip data to pixels of Array from GetRawTextureData?从 GetRawTextureData 将 AudioClip 数据映射到 Array 的像素?
【发布时间】:2021-08-30 11:34:32
【问题描述】:

GetRawTextureData() 返回纹理中所有像素的线性(一维)数组。

AudioClips 在一个一维数组中包含交错的(左和右)数据,这样索引代表 x(或时间),每个值是该 x/时间的左右信号的音量。偶数 = 左,奇数 = 右。

有没有一种简单的方法可以将它映射到从 GetRawTextureData() 返回的 NativeArray 中

我已经尝试过,只专注于显示左侧信号,但会产生奇怪的垂直结果:

void FillTextureOne (Texture2D wav_tex, float[] firstWave ) {
    var texdata = wav_tex.GetRawTextureData<Color32>( );
    for ( int i = 0; i < firstWave.Length ; i+=2 )
    {
        var positionnew =  i/2 * 256  + ( firstWave[i] + 1 ) * 128 ;
        texdata[( int )positionnew ] = black;
    }
    wav_tex.Apply( );
}

纹理大小为 256 x 256。 AudioClip 数据数组的长度为 512,其中存储的值范围从 -1 到 1,加一后乘以 128,尝试将它们垂直范围在 0 到 256 之间的尝试失败。

【问题讨论】:

  • 我不知道这是怎么工作的,但是 x + (y * width) 得到了位置。

标签: c# unity3d textures render-to-texture


【解决方案1】:

如果我理解您所困惑的解决方案,这里有一个简短的解释,说明它为什么起作用。要将二维数组正确映射到一维数组,您需要获取二维数组的widthheight,然后获取它们的乘积以提供合适的一维数组大小。下一步是确保您的二维数组位于row order or column order 中,这将决定您如何访问您的信息。一旦弄清楚了,有两个等式将允许您使用二维数组的宽度和高度而不是单一索引来访问二维数组格式的一维数组。为简单起见,我将再次使用您的索引器 xy 以及 widthheight

对于行顺序数组

yourOneDimensionalArray[width * x + y]

对于列顺序数组

yourOneDimensionalArray[height * y + x]

如果将一维数组分成相等的部分,可以将其视为潜在的二维数组。根据矩阵的顺序,它将根据中断的大小或可以拆分的部分来定义行或列的长度。

更直观的解释:

1 2 3 4 5 6 7 8 9 is a 1D array of size 1x9

1 2 3
4 5 6 is a 2D array row order of size 3x3
7 8 9

1 4 7 
2 5 8 is a 2D array column order of size 3x3
3 6 9

If we want to access the number 6 in these arrays, we would do as follows:
1DArray[5]
2DRowArray[1][2]
2DColumnArray[2][1]

From the previous equations, we can now take the indexes we have to see how they relate.

2DRowArray is row 1, column 2 or x = 1, y = 2 and our width is 3, so we take 1 * 3 + 2, which is 3 + 2 = 5 or our 1D index

Similarly, the 2DColumnArray is row 2, column 1 or x = 2, y = 1 and our height is 3, so we take 1 * 3 + 2, which is 3 + 2 = 5 or our 1D index.

我可以将此可视化解决方案扩展到256x256 网格,但我认为3x3 也应该能传达这个想法。如果您仍有疑问,请告诉我。

【讨论】:

  • y * width + x 是否只对我有用,因为网格是方形的?
  • @Confused 不!您也可以将非正方形二维数组映射到一维数组。在我的例子中,只要去掉最下面一行,找到 6 的方法仍然会得到相同的答案。同样,去掉列矩阵的最后一列,你会得到相同的答案。
  • 把它想象成一栋建筑,你正试图从电梯里找到一个特定楼层的房间——Y 楼的房间 X,这是一个二维数组。现在,想象一下,如果所有这些堆叠的楼层都变成了一栋长长的建筑。无需上 Y 层,您现在只需越过 Y 层,然后仍然找到您的 X。但是,由于现在没有楼层但您知道之前的高度和您想要的楼层,您仍然可以找到确切的 X 或您需要的房间高度 * Y + X。
  • 抱歉,我要问的是:您建议的是宽度 * x 或高度 * y,但我的 y * 宽度正在工作。如果我的纹理是非正方形的(例如 256 x 90),我认为它不应该按照我的方式工作。
  • 不是故意让你困惑的。有两个方程的原因取决于二维数组的打包方式。我相信大多数二维数组都是行顺序的,所以是的,您正在使用的当前方程很可能不适用于使用您正在使用的函数的非正方形。可以肯定的是,如果你能传入一个非正方形的纹理,看看它是否超出界限,你就会知道。
【解决方案2】:

在实时应用中,同步命令(传输像素)会不必要地降低 CPU 和 GPU 之间的并行度。不幸的是,您没有提供有关您的目标设备和操作系统的任何信息。如果你想获得最大的性能,你应该使用compute shaders

【讨论】:

  • 这些是计算出的正弦波、锯齿波、三角波和方波,在 Unity 的“OnAudioFilterRead”功能使用之前或之后,它们被绘制为每个最多 1024 个索引样本的样本。有没有办法将所有这些曲线计算作为计算着色器并有效地将最终数组发送到OnAudioFilterRead??
  • 是的,这一切都可以通过计算着色器完成。
  • 我不知道如何有效地完成 CPU 和 RAM 的最终曲线以从计算中为 OnAudioFilterRead 提供服务。这是这里的相反问题,通过Apply 对 GPU 进行 blit - 在这种情况下非常有效,因为它对所有更改都执行一次。
猜你喜欢
  • 1970-01-01
  • 2018-07-21
  • 2022-01-17
  • 2019-12-29
  • 2017-09-23
  • 1970-01-01
  • 1970-01-01
  • 2020-03-13
相关资源
最近更新 更多