AudioPlayer iOS and m4a
Asked Answered
D

3

5

I've made an app that plays music using AVAudioPlayer. It either uploads or downloads songs, writes them to Core Data, then recalls them to play when selected. All of the fifteen songs that I've been testing with operate normally using both the iPhone Music Client and my own computer.

However, three of them don't play back on the app. Specifically, I can upload these fifteen songs in any order, clear my Model.sqlite, download them again into the app, and find that three of them just don't play. They do, however, have the right title and artist.

Looking into this, I noticed that the difference is that the non-working files are .m4a. How do I play files of that format with AVAudioPlayer?

EDIT ("Whats "recalling?", what URL do you initialise AVAudioPlayer with?"):

There is a server with songs that the user can access through the app. After choosing which subset S to retrieve, the app then downloads S and writes it to a CoreModel using NSManagedObjectContext. Each song is stored as a separate entity with a unique ID and a relationship to a subset entity (in this case, S).

When I "recall" using the AppDelegate to get the right song using the context, the data is returned as well. I then initialize the AVAudioPlayer like so:

[[AVAudioPlayer alloc] initWithData:(NSData *)[currentSong valueForKey:@"data"] error:nil];

... So I wrote that and then realized that I haven't actually checked out what the error is (silly me). I found that it's OSStatus error 1954115647, which returns as Unsupported File Type. Looking into this a bit more, I found this iPhone: AVAudioPlayer unsupported file type. A solution is presented there as either trimming off bad data in the beginning or initializing from the contents of a URL. Is it possible to find where the data is written to in core model to feed that as the URL?

EDIT: (Compare files. Are they different?)

Yes, they are. I'm grabbing a sample .m4a file from my server, which was uploaded by the app, and comparing it to the one that's in iTunes. What I found is that the file is cut off before offset 229404 (out of 2906191 bytes), which starts 20680001 A0000E21. In the iTunes version, 0028D83B 6D646174 lies before those bytes. Before that is a big block of zeroes preceded by a big block of data preceded by iTunes encoding information. At the very top is more encoding information listing the file as being M4A.

Doublestop answered 25/4, 2013 at 23:19 Comment(0)
T
0

Are you sure your codec is supported in iOS? AVAudioPlayer is ought to play any format that iOS supports, you can read the list of supported formats here :http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html#//apple_ref/doc/uid/TP40009767-CH2-SW6 .

I will suggest you to try manually adding those files to your device through iTunes and playing them in iPod, if they won't play then the problem is not your code or sdk, but the format.

Teufert answered 26/4, 2013 at 0:19 Comment(1)
Yes, .m4a is supported in iOS and all of the files have no problem playing on the iPhone through regular means.Doublestop
P
0

How are you recalling them to play - are you writing them to a temporary file which has an m4a extension - this m4a extension is probably required.

Pusey answered 28/4, 2013 at 14:45 Comment(7)
I am writing them to core data, keyed by a unique ID, and then recalling them when it's time to play via that ID.Doublestop
Whats "recalling?", what URL do you initialise AVAudioPlayer with?Pusey
Edited to reflect question and more.Doublestop
Just to humour me, try writing them to a file with an m4a extension then playing them.Pusey
Do you mean in the app? Or on a computer? I haven't implemented it yet, but I was thinking of adjusting the model so that instead of saving the data as a field, I would save a file url as the field and write the actual data at that location similarly to the second answer in the linked SO. Then I could use initWithContentsOfUrlDoublestop
On the app, I tried doing both what I proposed above and adding an extension like you proposed. Neither worked.Doublestop
Cool, now you have the file on disk do a binary compare between it and your original file - has it become corrupted?Pusey
A
0

This is not a direct solution, but you probably shouldn't be saving the blobs in Core Data directly. Write the files to a cached location and save the file paths in Core Data. This will both use the database more efficiently and give you a local file path to give to your AVAudioPlayer, which will bypass the problem.

Alysiaalyson answered 2/5, 2013 at 17:9 Comment(2)
Or, if you're using the option in Core Data to allow external storage, you can find the location following this answer: #9802444 but that will only apply to objects over a certain size (currently 1 MB)Alysiaalyson
I adjusted the app to work s.t. I save the data to a local url dataLocation and then save that string to the coremodel. This works for regular songs, but it still doesn't work with m4a. I found this, #10546158, which seems to be describing the same issue. When I do an exportsession, I do get a larger file that includes the header information, but now I'm running into another issue with s3 putObject failing to receive it.Doublestop

© 2022 - 2024 — McMap. All rights reserved.