ExtAudioFile into a float buffer produces zeros - ios

I have this code in Swift 3 and my output is 0.0 zeros most of the time and rarely I see very small numbers to the e^-50
The fileURL is a recording.caf with sound in it.
Does anyone know what's up?
func readBuff(_ fileURL:CFURL) {
var fileRef:ExtAudioFileRef? = nil
let openStatus = ExtAudioFileOpenURL(fileURL , &fileRef)
guard openStatus == noErr else {
print("Failed to open audio file '\(fileURL)' with error \(openStatus)")
return
}
var audioFormat2 = AudioStreamBasicDescription()
audioFormat2.mSampleRate = 44100; // GIVE YOUR SAMPLING RATE
audioFormat2.mFormatID = kAudioFormatLinearPCM;
audioFormat2.mFormatFlags = kLinearPCMFormatFlagIsFloat;
audioFormat2.mBitsPerChannel = UInt32(MemoryLayout<Float32>.size) * 8
audioFormat2.mChannelsPerFrame = 1; // Mono
audioFormat2.mBytesPerFrame = audioFormat2.mChannelsPerFrame * UInt32(MemoryLayout<Float32>.size); // == sizeof(Float32)
audioFormat2.mFramesPerPacket = 1;
audioFormat2.mBytesPerPacket = audioFormat2.mFramesPerPacket * audioFormat2.mBytesPerFrame; // = sizeof(Float32)
//apply audioFormat2 to the extended audio file
ExtAudioFileSetProperty(fileRef!, kExtAudioFileProperty_ClientDataFormat,UInt32(MemoryLayout<AudioStreamBasicDescription>.size),&audioFormat2)
let numSamples = 1024 //How many samples to read in at a startTime
let sizePerPacket:UInt32 = audioFormat2.mBytesPerPacket // sizeof(Float32) = 32 byts
let packetsPerBuffer:UInt32 = UInt32(numSamples)
let outputBufferSize:UInt32 = packetsPerBuffer * sizePerPacket //4096
//so the 1 value of outputbuffer is a the memory location where we have reserved space
let outputbuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: MemoryLayout<UInt8>.size * Int(outputBufferSize))
var convertedData = AudioBufferList()
convertedData.mNumberBuffers = 1 //set this for Mono
convertedData.mBuffers.mNumberChannels = audioFormat2.mChannelsPerFrame // also = 1
convertedData.mBuffers.mDataByteSize = outputBufferSize
convertedData.mBuffers.mData = UnsafeMutableRawPointer(outputbuffer)
var frameCount:UInt32 = UInt32(numSamples)
while (frameCount > 0) {
Utility.check(ExtAudioFileRead(fileRef!,
&frameCount,
&convertedData),
operation: "Couldn't read from input file")
if frameCount == 0 {
Swift.print("done reading from file")
return
}
var arrayFloats:[Float] = []
let ptr = convertedData.mBuffers.mData?.assumingMemoryBound(to: Float.self)
var j = 0
var floatDataArray:[Double] = [882000]// SPECIFY YOUR DATA LIMIT MINE WAS 882000 , SHOULD BE EQUAL TO OR MORE THAN DATA LIMIT
if(frameCount > 0){
var audioBuffer:AudioBuffer = convertedData.mBuffers
let floatArr = UnsafeBufferPointer(start: audioBuffer.mData?.assumingMemoryBound(to: Float.self), count: 882000)
for i in 0...1024{
//floatDataArray[j] = Double(floatArr[i]) //put your data into float array
// print("\(floatDataArray[j])")
floatDataArray.append(Double(floatArr[i]))
print(Float((ptr?[i])!))
j += 1
}
// print(floatDataArray)
}
}
}
I'm reading from
guard let fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, "./output.caf" as CFString!, .cfurlposixPathStyle, false) else {
// unable to create file
exit(-1)
}
steps after recording:
Swift.print("Recording, press <return> to stop:\n")
// wait for a key to be pressed
getchar()
// end recording
Swift.print("* recording done *\n")
recorder.running = false
// stop the Queue
Utility.check(AudioQueueStop(queue!, true),
operation: "AudioQueueStop failed")
// a codec may update its magic cookie at the end of an encoding session
// so reapply it to the file now
Utility.applyEncoderCookie(fromQueue: queue!, toFile: recorder.recordFile!)
// cleanup
AudioQueueDispose(queue!, true)
AudioFileClose(recorder.recordFile!)
readBuff(fileURL)

You're setting up your ExtAudioFile and its client format, but you're not actually reading from it (with ExtAudioFileRead), so your "output" is actually uninitialised, and in your case, very small.

Related

Deserialize BinaryData and mapping to an object

I have a small project where I have a list with questions (96 questions).
I try to serialize that list of questions into a BinaryData and to save that result in CoreData.
After I want to deserialize that BinaryData from CoreData and to map the values to an object.
The problem is that my serialization I think is working, but the deserialization is not working for some reason.
This line of code is not called when I run the code and I don't know why:
https://github.com/tygruletz/AddTagsForRows/blob/master/PreloadQuestions/Controller/Communication/TTable.swift#L457
To generate a report in CoreData just click Next-> Next-> Finish.
Here is the code for deserialization:
func deStreamBin(stream: InputStream, format: EStreamFormat){
var protocolByte: UInt8 = 0
var columns: UInt16 = 0
var rows: UInt32 = 0
var tableFlag: ETableFlags
//We should scroll through 0's until we find '1' indicating the start of a table
while protocolByte != 0x01 {
protocolByte = deserializeByte(stream: stream)
}
// Header
_ = deserializeUInt32(stream: stream)
columns = deserializeUInt16(stream: stream)
rows = deserializeUInt32(stream: stream)
print("Number of rows in TTable: \(rows)")
tableFlag = ETableFlags(rawValue: UInt(deserializeUInt16(stream: stream))) ?? ETableFlags.none // 0x0001 = Exception, 0x002 = Interrupt
_ = deserializeByte(stream: stream) // Flags (0x01 = Meta, 0x02 = Last Row, 0x00 = The rest)
// Read the Meta Details
var tMeta: [TMeta] = []
for _ in 0..<columns {
guard let type = EMeta(rawValue: deserializeString(stream: stream, length: 1)) else {return}
var name = ""
if format == EStreamFormat.bin1 {
let nameLength = Int(deserializeByte(stream: stream))
name = deserializeString(stream: stream, length: nameLength)
}
else{
// No names for the bin2
}
tMeta.append(TMeta(type: type, name: name))
}
self.tMeta = tMeta
self.flags = tableFlag
for _ in 0..<rows {
let row: TRow = TRow(tMeta: tMeta)
_ = deserializeUInt32(stream: stream) // Row Number
_ = deserializeByte(stream: stream) // Flags (0x01 = Meta, 0x02 = Last Row, 0x00 = The rest)
for i in 0..<tMeta.count {
let m: TMeta = tMeta[i]
switch m.type {
// Integer (Int32)
case EMeta.i:
row.cell[i] = TCell(i: Int(deserializeInt32(stream: stream)))
// Boolean
case EMeta.b:
row.cell[i] = TCell(b: deserializeBoolean(stream: stream))
// String (length as UInt32, followed by array of chars)
case EMeta.s:
let nLenString = Int(deserializeUInt32(stream: stream))
row.cell[i] = TCell(s: deserializeString(stream: stream, length: nLenString))
// DateTime (BCD Array: YY YY MM DD hh mm ss)
case EMeta.t:
row.cell[i] = TCell(date: deserializeDateTime(stream: stream) ?? Date())
// Database Bytes (Length as Int32, followed by array of bytes)
case EMeta.z:
let nLenBytes = Int(deserializeUInt32(stream: stream))
row.cell[i] = TCell(data: deserializeByteArray(stream: stream, lenght: Int32(nLenBytes)))
// Double (IEEE 8-byte double)
case EMeta.d:
row.cell[i] = TCell(d: deserializeDouble(stream: stream))
// Single Byte
case EMeta.u:
row.cell[i] = TCell(b: deserializeByte(stream: stream))
}
}
do {
try add(row: row)
} catch{
print("deStreamBin: Can't add the row in tMeta: \(error)")
}
}
}
Please help me to deserialize my BinaryData to be able to map the values to an object.
Thanks in advance !

Thread 1: Fatal error: Index out of range when index is less then array count

I am getting error Thread 1: Fatal error: Index out of range on
func ReaderConverterCallback(_ converter: AudioConverterRef,
_ packetCount: UnsafeMutablePointer<UInt32>,
_ ioData: UnsafeMutablePointer<AudioBufferList>,
_ outPacketDescriptions: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>?>?,
_ context: UnsafeMutableRawPointer?) -> OSStatus {
let reader = Unmanaged<Reader>.fromOpaque(context!).takeUnretainedValue()
//
// Make sure we have a valid source format so we know the data format of the parser's audio packets
//
guard let sourceFormat = reader.parser.dataFormat else {
return ReaderMissingSourceFormatError
}
//
// Check if we've reached the end of the packets. We have two scenarios:
// 1. We've reached the end of the packet data and the file has been completely parsed
// 2. We've reached the end of the data we currently have downloaded, but not the file
//
let packetIndex = Int(reader.currentPacket)
let packets = reader.parser.packets
let isEndOfData = packetIndex >= packets.count - 1
if isEndOfData {
if reader.parser.isParsingComplete {
packetCount.pointee = 0
return ReaderReachedEndOfDataError
} else {
return ReaderNotEnoughDataError
}
}
//
// Copy data over (note we've only processing a single packet of data at a time)
//
let packet = packets[packetIndex] <--------- Thread 1: Fatal error: Index out of range on
var data = packet.0
let dataCount = data.count
ioData.pointee.mNumberBuffers = 1
ioData.pointee.mBuffers.mData = UnsafeMutableRawPointer.allocate(byteCount: dataCount, alignment: 0)
_ = data.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<UInt8>) in
memcpy((ioData.pointee.mBuffers.mData?.assumingMemoryBound(to: UInt8.self))!, bytes, dataCount)
}
ioData.pointee.mBuffers.mDataByteSize = UInt32(dataCount)
//
// Handle packet descriptions for compressed formats (MP3, AAC, etc)
//
let sourceFormatDescription = sourceFormat.streamDescription.pointee
if sourceFormatDescription.mFormatID != kAudioFormatLinearPCM {
if outPacketDescriptions?.pointee == nil {
outPacketDescriptions?.pointee = UnsafeMutablePointer<AudioStreamPacketDescription>.allocate(capacity: 1)
}
outPacketDescriptions?.pointee?.pointee.mDataByteSize = UInt32(dataCount)
outPacketDescriptions?.pointee?.pointee.mStartOffset = 0
outPacketDescriptions?.pointee?.pointee.mVariableFramesInPacket = 0
}
packetCount.pointee = 1
reader.currentPacket = reader.currentPacket + 1
return noErr;
}
even if there is packetIndex is less then packets.count.
Note: Please compare both question before marking it duplicate. Reference possible duplicate doesn't show that index of array is less than array count.
I am using this https://github.com/syedhali/AudioStreamer/ library for playing audio from url.
It looks like a Multi-Thread problem. According to the printed logs, the index seems ok, but another thread may change the data 'packets', that causes the crash. Please consider locking data-related operations between threads.
Additional analyzation: according to the following lines, packets may be shared between threads.
let reader = Unmanaged<Reader>.fromOpaque(context!).takeUnretainedValue()
//......
let packets = reader.parser.packets
Suggestion: check if somewhere the Unmanaged<Reader> change the parser.packets, and make a lock strategy.

H.264 Decoder not working properly?

I've gone over the code for this decoder for elementary h.264 bitstreams a hundred times, tweaking things along the way, with no luck. When I send the output CMSampleBuffers to an AVSampleBufferDisplayLayer, they don't appear, presumably because there's something wrong with how I'm decoding them.
I get no error messages anywhere; the AVSampleBufferDisplayLayer has no error and "status" is "1" (aka .rendering), CMSampleBufferIsValid() returns "true" on the outputted CMSampleBuffers, and I encounter no errors in my decoder either.
I'm stumped and my hope is that a more experienced developer can catch something that I'm missing.
I input raw bytes here (typealias FrameData = [UInt8])
func interpretRawFrameData(_ frameData: inout FrameData) -> CMSampleBuffer? {
let size = UInt32(frameData.count)
var naluType = frameData[4] & 0x1F
var frame: CMSampleBuffer?
// The start indices for nested packets. Default to 0.
var ppsStartIndex = 0
var frameStartIndex = 0
switch naluType {
// SPS
case 7:
print("===== NALU type SPS")
for i in 4..<40 {
if frameData[i] == 0 && frameData[i+1] == 0 && frameData[i+2] == 0 && frameData[i+3] == 1 {
ppsStartIndex = i
spsSize = i - 4 // Does not include the size of the header
sps = Array(frameData[4..<i])
// Set naluType to the nested PPS packet's NALU type
naluType = frameData[i + 4] & 0x1F
break
}
}
// If nested frame was found, fallthrough
if ppsStartIndex != 0 { fallthrough }
// PPS
case 8:
print("===== NALU type PPS")
for i in ppsStartIndex+4..<ppsStartIndex+34 {
if frameData[i] == 0 && frameData[i+1] == 0 && frameData[i+2] == 0 && frameData[i+3] == 1 {
frameStartIndex = i
ppsSize = i - spsSize - 8 // Does not include the size of the header. Subtract 8 to account for both the SPS and PPS headers
pps = Array(frameData[ppsStartIndex+4..<i])
// Set naluType to the nested packet's NALU type
naluType = frameData[i+4] & 0x1F
break
}
}
// If nested frame was found, fallthrough
if frameStartIndex != 0 { fallthrough }
// IDR frame
case 5:
print("===== NALU type IDR frame");
// Replace start code with size
let adjustedSize = size - UInt32(ppsSize) - UInt32(spsSize) - 8
var blockSize = CFSwapInt32HostToBig(adjustedSize)
memcpy(&frameData[frameStartIndex], &blockSize, 4)
if createFormatDescription() {
frame = decodeFrameData(Array(frameData[frameStartIndex...]))
}
// B/P frame
default:
print("===== NALU type B/P frame");
// Replace start code with size
var blockSize = CFSwapInt32HostToBig(size)
memcpy(&frameData[frameStartIndex], &blockSize, 4)
frame = decodeFrameData(Array(frameData[frameStartIndex...]))
break;
}
return frame != nil ? frame : nil
}
And this is where the actual decoding happens:
private func decodeFrameData(_ frameData: FrameData) -> CMSampleBuffer? {
let bufferPointer = UnsafeMutablePointer<UInt8>(mutating: frameData)
let size = frameData.count
var blockBuffer: CMBlockBuffer?
var status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
bufferPointer,
size,
kCFAllocatorNull,
nil, 0, frameData.count,
0, &blockBuffer)
if status != kCMBlockBufferNoErr { return nil }
var sampleBuffer: CMSampleBuffer?
let sampleSizeArray = [size]
status = CMSampleBufferCreateReady(kCFAllocatorDefault,
blockBuffer,
formatDesc,
1, 0, &sampleTimingInfo,
1, sampleSizeArray,
&sampleBuffer)
if let buffer = sampleBuffer, status == kCMBlockBufferNoErr {
let attachments: CFArray? = CMSampleBufferGetSampleAttachmentsArray(buffer, true)
if let attachmentArray = attachments {
let dic = unsafeBitCast(CFArrayGetValueAtIndex(attachmentArray, 0), to: CFMutableDictionary.self)
let key = Unmanaged.passUnretained(kCMSampleAttachmentKey_DisplayImmediately).toOpaque()
let val = Unmanaged.passUnretained(kCFBooleanTrue).toOpaque()
CFDictionarySetValue(dic,
key,
val)
}
print("===== Successfully created sample buffer")
return buffer
}
return nil
}
Other things to note:
The formatDescription contains the correct information (mediaType = "vide", mediaSubType = "avc1", dimensions = "640x480")
The bitstream I'm decoding always groups the SPS, PPS, and IDR frames together and sends them as one big packet every 20 or so frames. Every other time, an individual B/P frame is sent.
Thanks!
That code was pretty ugly so I decided to touch it up a little bit. Turned out that did the trick. Something must have been wrong in there.
Anyways, here's a working version. It sends the decoded & decompressed frame to its delegate. Ideally, whoever calls interpretRawFrameData would be returned a displayable frame, and I'll work on that, but in the meantime this works too.
https://github.com/philipshen/H264Decoder

Finding cause of newRenderPipelineStateWithDescriptor failure

I'm trying to create a pipeline state in swift and the app crashes with SIGABRT. I've put the call to newRenderPipelineStateWithDescriptor within a try catch block. Why is it not caching it?
Here's the code,
let defaultLibrary = device.newDefaultLibrary()!
let fragmentProgram = defaultLibrary.newFunctionWithName("passThroughFragment")!
let vertexProgram = defaultLibrary.newFunctionWithName("passGeometry")!
// check TexturedVertex
let vertexDesc = MTLVertexDescriptor()
vertexDesc.attributes[0].format = .Float3
vertexDesc.attributes[0].offset = 0
vertexDesc.attributes[0].bufferIndex = 0
vertexDesc.attributes[1].format = .Float3
vertexDesc.attributes[0].offset = sizeof(Vec3)
vertexDesc.attributes[0].bufferIndex = 0
vertexDesc.attributes[2].format = .Float2
vertexDesc.attributes[0].offset = sizeof(Vec3) * 2
vertexDesc.attributes[0].bufferIndex = 0
vertexDesc.layouts[0].stepFunction = .PerVertex
vertexDesc.layouts[0].stride = sizeof(TexturedVertex)
let pipelineStateDescriptor = MTLRenderPipelineDescriptor()
pipelineStateDescriptor.vertexFunction = vertexProgram
pipelineStateDescriptor.fragmentFunction = fragmentProgram
//pipelineStateDescriptor.vertexDescriptor = vertexDesc
pipelineStateDescriptor.colorAttachments[0].pixelFormat = view.colorPixelFormat
pipelineStateDescriptor.colorAttachments[0].blendingEnabled = false
pipelineStateDescriptor.sampleCount = view.sampleCount
do {
// SIGABRT will happen here when enabling .vertexDescriptor = vertexDesc
try pipelineState = device.newRenderPipelineStateWithDescriptor(pipelineStateDescriptor)
} catch let error {
print("Failed to create pipeline state, error \(error)")
}
The code above doesn't crash, until I enable this line,
pipelineStateDescriptor.vertexDescriptor = vertexDesc
To give a bit of background, my vertex shader used to receive a packed_float4 buffer as input but I'm trying to update it to a struct, as defined in the MTLVertexDescriptor above.
The frustrating thing is that the app just crashes without giving any hints of what's wrong.
Is there any way of get error messages when calling device.newRenderPipelineStateWithDescriptor?
Edit:
This fixes the crash,
vertexDesc.attributes[0].format = .Float3
vertexDesc.attributes[0].offset = 0
vertexDesc.attributes[0].bufferIndex = 0
vertexDesc.attributes[1].format = .Float3
vertexDesc.attributes[1].offset = sizeof(Vec3)
vertexDesc.attributes[1].bufferIndex = 0
vertexDesc.attributes[2].format = .Float2
vertexDesc.attributes[2].offset = sizeof(Vec3) * 2
vertexDesc.attributes[2].bufferIndex = 0
But apparently there's no way to make newRenderPipelineStateWithDescriptor to throw an exception because of that at the moment.

How to resolve un-ordered JSON dictionary retrieved from YouTube Api?

I've been stuck on this for a while and cannot think logically how to resolve this, and would like some help.
Basically, I'm using the YouTube api to fetch all the video IDs from a changel. I store each of these IDs in an array, and I loop through its indices, each time calling this: https://developers.google.com/youtube/v3/docs/videos/list
This allows me to get the video duration of each video, where I put it in another array of AnyObjects and convert it to a recognizable format.
Here's the output of my videoIDs array, as I fetch it in groups of 10:
videoIDs = ["173ZNVycdQo", "NztC0z1JNq0", "U2C81DNHw2M", "09XKD2sS60E",
"Wc0cVjv44Xc", "ENKHANzmeh4", "mIW5trLZJcM", "KW0ehzTVo-s",
"1MyVzWIwFs4", "HyTQBpZeJCc"]
The problem is in the for loop as shown here:
for (var j = 0; j < self.videoIDs.count; j++)
{
self.getDurations("https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics,status&id=\(self.videoIDs[j])&key=\(self.apiKey)")
}
And Here's my getDurations function:
func getDurations(urlString: String)
{
let targetURL = NSURL(string: urlString)
performGetRequest(targetURL, completion: { (data, HTTPStatusCode, error) -> Void in
if HTTPStatusCode == 200 && error == nil
{
do
{
self.resultsVideoDurationsDict = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as! Dictionary<NSObject, AnyObject>
print("resultsDict = \(self.resultsVideoDurationsDict)")
let items = self.resultsVideoDurationsDict["items"] as AnyObject!
// Loop through all items and add it to another dictionary
for (var i = 0; i < items.count; i++)
{
self.unformattedDurations.append(items[i])
}
}
catch
{
print(error)
}
}
else
{
print("HTTP Status Code = \(HTTPStatusCode)")
print("Error while loading channel details: \(error)")
}
})
}
At every iteration, the JSON of self.resultsVideoDurationsDict is different, i.e. the order of the video IDs within the videoIDs array does not correspond to the same order of data output from the JSON.
I know that due to time delays in the NSURLSession, some data may be fetched earlier than others.
Is there a way to remedy this to way to ensure my self.unformattedDurations contains the ordered data corresponding to the data in the videoIDs array?
Thanks.
UPDATE:
Here's one possible output of self.resultsVideoDurationsDict:
resultsDict = [etag: "DsOZ7qVJA4mxdTxZeNzis6uE6ck/EfACrkkmn5_QpCjD89FgcTdjxVY", kind: youtube#videoListResponse, items: (
{
contentDetails = {
caption = false;
definition = hd;
dimension = 2d;
duration = PT11M29S;
licensedContent = 0;
};
etag = "\"DsOZ7qVJA4mxdTxZeNzis6uE6ck/7wjJ90GVQP7Bo9GwdX8LfdJ8jdg\"";
id = HyTQBpZeJCc;
kind = "youtube#video";
snippet = {
categoryId = 22;
channelId = UC5ltMmeC4YFaart1SSXdmAg;
channelTitle = "Viet My Television";
description = "";
liveBroadcastContent = none;
localized = {
description = "";
title = "PSCD TIEC QUAN 4";
};
publishedAt = "2016-02-02T17:31:58.000Z";
thumbnails = {
default = {
height = 90;
url = "https://i.ytimg.com/vi/HyTQBpZeJCc/default.jpg";
width = 120;
};
high = {
height = 360;
url = "https://i.ytimg.com/vi/HyTQBpZeJCc/hqdefault.jpg";
width = 480;
};
maxres = {
height = 720;
url = "https://i.ytimg.com/vi/HyTQBpZeJCc/maxresdefault.jpg";
width = 1280;
};
medium = {
height = 180;
url = "https://i.ytimg.com/vi/HyTQBpZeJCc/mqdefault.jpg";
width = 320;
};
standard = {
height = 480;
url = "https://i.ytimg.com/vi/HyTQBpZeJCc/sddefault.jpg";
width = 640;
};
};
title = "PSCD TIEC QUAN 4";
};
statistics = {
commentCount = 0;
dislikeCount = 0;
favoriteCount = 0;
likeCount = 0;
viewCount = 14;
};
status = {
embeddable = 1;
license = youtube;
privacyStatus = public;
publicStatsViewable = 1;
uploadStatus = processed;
};
}
), pageInfo: {
resultsPerPage = 1;
totalResults = 1;
}]
The id of that result is HyTQBpZeJCc, which corresponds to the 9th index of the videoIDs array, not the first index. The first output should be for video ID 173ZNVycdQo. Therefore, different outputs are produced at runtime.

Resources