Proper use of withMemoryRebound - swift

I am using the following code:
audioBuff.audioBuffer.floatChannelData![0].withMemoryRebound(to: DSPComplex.self, capacity: bufferSizePOT / 2) {dspComplexStream in
vDSP_ctoz(dspComplexStream, 2, &output, 1, UInt(bufferSizePOT / 2))
}
I'd like to jump to some further samples doing this:
audioBuff.audioBuffer.floatChannelData![1024].withMemoryRebound(to: DSPComplex.self, capacity: bufferSizePOT / 2) {dspComplexStream in
vDSP_ctoz(dspComplexStream, 2, &output, 1, UInt(bufferSizePOT / 2))
}
when doing so, I have an EXC_BAD_ACCESS (code=1, address=0x0)
someone could explain how to use it properly?
I used the .withMemoryRebound because i initialy tried:
vDSP_ctoz(audioBuff.audioBuffer.floatChannelData!, 2, &output, 1, UInt(bufferSizePOT / 2))
which gave me the error:
Cannot convert value of type 'UnsafePointer>' to expected argument type 'UnsafePointer'
what I would like to do is to move into the audioBuff.audioBuffer.floatChannelData! by chunks to do FFTs

audioBuffer.floatChannelData![0] represents a pointer to samples of channel#0.
You can access samples of channel#1 with audioBuffer.floatChannelData![1] when the buffer is non-interleved stereo.
But, I believe any of the Apple's sound hardware does not support channel#1024.
You may need to write something like this when you want to use the samples from the 1024th:
audioBuffer.floatChannelData![0]
.advanced(by: 1024)
.withMemoryRebound(to: DSPComplex.self, capacity: bufferSizePOT / 2) {
dspComplexStream in
vDSP_ctoz(dspComplexStream, 2, &output, 1, UInt(bufferSizePOT / 2))
}

Related

For What Can I Use Transform.lossyScale in Unity For Example in this Script

Body<>
private float UnitPerPixel;
UnitPerPixel = PrefabsWallTile.transform.lossyScale.x;
float HalfUnitPerPixel = UnitPerPixel / 2f;
Have you tried reading the API?
-> it is the absolute scale after all parent object scaling has been applied. In contrary to the localScale which is only the scale in the parents space.
For instance let's say you have a hierarchy with local sales (the ones displayed and configured in the Inspector) like e.g.
A (2, 2, 2)
|--B (5, 5, 5)
|--C (3, 3, 3)
then object C with a localScale of 3,3,3 will have a lossy scale of 30, 30, 30 which is the result of
2 * 5 * 3, 2 * 5 * 3, 2 * 5 * 3

Perform normalization using Accelerate framework

I need to perform simple math operation on Data that contains RGB pixels data. Currently Im doing this like so:
let imageMean: Float = 127.5
let imageStd: Float = 127.5
let rgbData: Data // Some data containing RGB pixels
let floats = (0..<rgbData.count).map {
(Float(rgbData[$0]) - imageMean) / imageStd
}
return Data(bytes: floats, count: floats.count * MemoryLayout<Float>.size)
This works, but it's too slow. I was hoping I could use the Accelerate framework to calculate this faster, but have no idea how to do this. I reserved some space so that it's not allocated every time this function starts, like so:
inputBufferDataNormalized = malloc(width * height * 3) // 3 channels RGB
I tried few functions, like vDSP_vasm, but I couldn't make it work. Can someone direct me to how to use it? Basically I need to replace this map function, because it takes too long time. And probably it would be great to use pre-allocated space all the time.
Following up on my comment on your other related question. You can use SIMD to parallelize the operation, but you'd need to split the original array into chunks.
This is a simplified example that assumes that the array is exactly divisible by 64, for example, an array of 1024 elements:
let arr: [Float] = (0 ..< 1024).map { _ in Float.random(in: 0...1) }
let imageMean: Float = 127.5
let imageStd: Float = 127.5
var chunks = [SIMD64<Float>]()
chunks.reserveCapacity(arr.count / 64)
for i in stride(from: 0, to: arr.count, by: 64) {
let v = SIMD64.init(arr[i ..< i+64])
chunks.append((v - imageMean) / imageStd) // same calculation using SIMD
}
You can now access each chunk with a subscript:
var results: [Float] = []
results.reserveCapacity(arr.count)
for chunk in chunks {
for i in chunk.indices {
results.append(chunk[i])
}
}
Of course, you'd need to deal with a remainder if the array isn't exactly divisible by 64.
I have found a way to do this using Accelerate. First I reserve space for converted buffer like so
var inputBufferDataRawFloat = [Float](repeating: 0, count: width * height * 3)
Then I can use it like so:
let rawBytes = [UInt8](rgbData)
vDSP_vfltu8(rawBytes, 1, &inputBufferDataRawFloat, 1, vDSP_Length(rawBytes.count))
vDSP.add(inputBufferDataRawScalars.mean, inputBufferDataRawFloat, result: &inputBufferDataRawFloat)
vDSP.multiply(inputBufferDataRawScalars.std, inputBufferDataRawFloat, result: &inputBufferDataRawFloat)
return Data(bytes: inputBufferDataRawFloat, count: inputBufferDataRawFloat.count * MemoryLayout<Float>.size)
Works very fast. Maybe there is better function in Accelerate, if anyone know of it, please let me know. It need to perform function (A[n] + B) * C (or to be exact (A[n] - B) / C but the first one could be converted to this).

LibreOffice floating point precision

I am doing calculations on date and time using floating-point numbers. However, I notice that the calculated value is not as expected. Here is the code snippet.
Dim sTemp As Single, sLineDateTime As Single
Dim strTemp As String
strTemp = "2019-02-25"
sLineDateTime = DateValue(DateSerial(Left(strTemp, 4), Mid(strTemp, 6, 2), Right(strTemp, 2)))
strTemp = ""21:47:42"
REM TODO Time is being rounded off. Check
sTemp = TimeValue(TimeSerial(Left(strTemp, 2), Mid(strTemp, 4, 2), Right(strTemp, 2)))
sLineDateTime = sLineDateTime + sTemp
The output of the above computation is sLineDateTime="43521.906250" which when converted to date/time is "Mon 25-Feb-2019 09:45:00 PM". The actual value expected is "43521.908125" which translates to error of "0.001875000001746" or in other words 2 minutes 42 seconds. Any suggestions on how I can overcome this problem?
I did try before posting this and it did not help. I switched to using dates which is working perfectly for me now. Here is the code.
strTemp = "2019-02-25"
dLineDateTime = DateSerial(Left(strTemp, 4), Mid(strTemp, 6, 2), Right(strTemp, 2))
strTemp = "21:47:42"
dLineDateTime = dLineDateTime + TimeSerial(Left(strTemp, 2), Mid(strTemp, 4, 2), Right(strTemp, 2))

How do I calculate average in Observable<Double>?

I was thinking about using RxJava2Extensions, but for some reason these function don't return Maybe/Single<Double> which is a bit strange, IMO.
MathFlowable.averageDouble(Flowable.range(1, 10))
.test()
.assertResult(5.5);
Flowable.just(5, 1, 3, 2, 4)
.to(MathFlowable::min)
.test()
.assertResult(1);

Torch: back-propagation from loss computed over a subset of the output

I have a simple convolutional neural network, whose output is a single channel 4x4 feature map. During training, the (regression) loss needs to be computed only on a single value among the 16 outputs. The location of this value will be decided after the forward pass. How do I compute the loss from just this one output, while making sure all irrelevant gradients are zero'ed out during back-prop.
Let's say I have the following simple model in torch:
require 'nn'
-- the input
local batch_sz = 2
local x = torch.Tensor(batch_sz, 3, 100, 100):uniform(-1,1)
-- the model
local net = nn.Sequential()
net:add(nn.SpatialConvolution(3, 128, 9, 9, 9, 9, 1, 1))
net:add(nn.SpatialConvolution(128, 1, 3, 3, 3, 3, 1, 1))
net:add(nn.Squeeze(1, 3))
print(net)
-- the loss (don't know how to employ it yet)
local loss = nn.SmoothL1Criterion()
-- forward'ing x through the network would result in a 2x4x4 output
y = net:forward(x)
print(y)
I have looked at nn.SelectTable and it seems like if I convert the output into tabular form I would be able to implement what I want?
This is my current solution. It works by splitting the output into a table, and then using nn.SelectTable():backward() to get the full gradient:
require 'nn'
-- the input
local batch_sz = 2
local x = torch.Tensor(batch_sz, 3, 100, 100):uniform(-1,1)
-- the model
local net = nn.Sequential()
net:add(nn.SpatialConvolution(3, 128, 9, 9, 9, 9, 1, 1))
net:add(nn.SpatialConvolution(128, 1, 3, 3, 3, 3, 1, 1))
net:add(nn.Squeeze(1, 3))
-- convert output into a table format
net:add(nn.View(1, -1)) -- vectorize
net:add(nn.SplitTable(1, 1)) -- split all outputs into table elements
print(net)
-- the loss
local loss = nn.SmoothL1Criterion()
-- forward'ing x through the network would result in a (2)x4x4 output
y = net:forward(x)
print(y)
-- returns the output table's index belonging to specific location
function get_sample_idx(feat_h, feat_w, smpl_idx, feat_r, feat_c)
local idx = (smpl_idx - 1) * feat_h * feat_w
return idx + feat_c + ((feat_r - 1) * feat_w)
end
-- I want to back-propagate the loss of this sample at this feature location
local smpl_idx = 2
local feat_r = 3
local feat_c = 4
-- get the actual index location in the output table (for a 4x4 output feature map)
local out_idx = get_sample_idx(4, 4, smpl_idx, feat_r, feat_c)
-- the (fake) ground-truth
local gt = torch.rand(1)
-- compute loss on the selected feature map location for the selected sample
local err = loss:forward(y[out_idx], gt)
-- compute loss gradient, as if there was only this one location
local dE_dy = loss:backward(y[out_idx], gt)
-- now convert into full loss gradient (zero'ing out irrelevant losses)
local full_dE_dy = nn.SelectTable(out_idx):backward(y, dE_dy)
-- do back-prop through who network
net:backward(x, full_dE_dy)
print("The full dE/dy")
print(table.unpack(full_dE_dy))
I would really appreciate it somebody points out a simpler OR more efficient method.