I have an app that uses .aupreset files along with .wav samples to define instruments that are loaded into an AUSampler audio unit.
The .aupreset files reference the .wav files with absolute paths. As described in Technical Note 2283, if the audio files cannot be found at the original path, then the system searches in the Bundle Directory, NSLibraryDirectory, NSDocumentsDirectory, and NSDownloadsDirectory, in that order.
I can get the instruments working in the app bundle, but now I'm trying to support downloaded instruments. If I put the content in <NSLibraryDirectory>/Sounds/, the AUSampler can't find the .wav samples, but if I put it in <NSDocumentsDirectory>/Sounds/, it works. I don't want to clutter the Documents directory with the instruments though, as that folder shows up in iTunes.
This is the error printed by the AUSampler:
09:27:25.251 ERROR: [0x19989c310] 372: Failed to locate sample 'file:///Sounds/trance/square-lead/Square-12000Hz.wav'
Also, I can't even create a directory at the NSDownloadsDirectory location - I just get an Operation not permitted error.
Has anyone successfully loaded samples from the Library before?
(This is on iOS 8.)
I received this explanation from an Apple Engineer:
It turns out the documentation for this is incorrect for iOS: AUSampler will only look in NSDocumentDirectory and the NSDownloadsDirectory in addition to the bundle. These are the recommended locations for storing application-specific data, if you aren't going to store it in the bundle, or you wish to enable users to add additional content to the app.
For OSX, the NSLibraryDirectory is also available.
From my own testing, however, you can't use the NSDownloadsDirectory either, as trying to create the directory returns an error ("The operation couldn’t be completed. Operation not permitted"). So it would appear that the only options on iOS are loading from the bundle or from the Documents directory.
This isn't ideal when you also want to enable iTunes File Sharing for other content, so I did think of another workaround: put the content in an arbitrary location, and when loading the .aupreset file, rewrite all the file references to refer to that location before setting it on the Audio Unit.
Yes, you can definitely load samples from the Library directory.
I thought you had to create the library directory, but I was mistaken. It is the Application Support directory I was thinking of.
Related
I have a data file that I need to include with my app when I distribute it. When loading any files in the app, I prefix the file name with:
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
This works great for anything I create within the app (and for reading back), like files I download in response to a user action. But I can't for the life of me figure out how to place files there when I build my app in Visual Studio.
I've tried making a "Documents" subdirectory in the special "Resources" folder, but that didn't work (I tried setting the "Build Action" to both BundleResource and Content). When I look at the folder for my app (from using the simulator) I can see that in the "Documents" folder there's all the files I downloaded, but I can't find my data file that I'm trying to bundle ahead of time. I even searched my entire hard drive on the Mac and still couldn't find said data file.
The data file isn't an image, if it matters. Just raw binary data. How do I set it up so that this file goes into the proper documents directory at compile time, so that I can read it using the SpecialFolder.MyDocuments prefix? Thanks.
You can't. You can include files in your app bundle, and then at startup copy them from the bundle into a user folder. But this won't happen automatically.
If an app requires hundreds of audio files (they're small, 5-25KB), is it better to put them in an asset catalog or the documents directory? I've tried both approaches and they don't seem much different, it's a pain to manage hundreds of files in the project navigator either way and it's the same app filesize for both.
Since you wish to bundle your audio files with your app, you can't use the Documents folder. The use of the Documents folder is a runtime feature than can only be used once your app has been installed from the App Store and run by the user.
To include the files with your app so they exist immediately, they must be part of your app's resource bundle. Whether you use an asset catalog or simply store them in the bundle is up to you, but it's not possible to package them in the Documents folder since there is no Documents folder until the first time the app is run by the user.
So far, I've found one thing that influences whether to "just" put audio files in the app bundle or to put it in the asset catalog portion of the app bundle.
When you put audio files in the asset catalog, it's available as data, there's no URL. As I understand it now, if you want a URL, you'll have to extract the data and create a file, which is double work.
When you have a URL that's available automatically when you "just" put audio files in the app bundle, it gives you more options. Like using AVQueuePlayer with AVPlayerItem. AVPlayerItem only takes a URL, not data. If you wanted to play audio files one after another from the asset catalog, it's more work, you have to write code for AVAudioPlayerDelegate, whereas with AVQueuePlayer, you just provide an array of AVPlayerItems.
I suspect that there may be more advantages having a URL to reference and am not seeing the advantages the asset catalog has yet, so my opinion is subject to change.
I have an app written in Swift that is similar to a soundboard. Currently I just have a bunch of mp3s in the apps main bundle. Is it possible to remotely add more mp3s into the apps main bundle and then change a variable in the code to account for the new mp3s? I want it so that I can dynamically add new mp3s without going through the whole app review process. Ideally a user would be able to open the app the next day and find that 15 new mp3s have been added without having to download an update. Is this a possibility?
You can’t write to the main bundle on iOS. Its contents are
cryptographically signed as a part of the App Store submission
process; modifying its contents would prevent the application from
running.
Reference from THIS answer.
And you can get more information from this post: File write with [NSBundle mainBundle] fails.
File System Programming Guide:
< Application_Home>/AppName.app
This is the bundle directory containing the app itself. Do not write
anything to this directory. To prevent tampering, the bundle directory
is signed at installation time. Writing to this directory changes the
signature and prevents your app from launching again.
< Application_Home>/Documents/
Use this directory to store critical user documents and app data
files. Critical data is any data that cannot be recreated by your app,
such as user-generated content. The contents of this directory can be
made available to the user through file sharing. The contents of this
directory are backed up by iTunes.
< Application_Home>/Library/
This directory is the top-level directory for files that are not user
data files. You typically put files in one of several standard
subdirectories but you can also create custom subdirectories for files
you want backed up but not exposed to the user. You should not use
this directory for user data files. The contents of this directory
(with the exception of the Caches subdirectory) are backed up by
iTunes. For additional information about the Library directory, see
“The Library Directory Stores App-Specific Files.”
You can read THIS if you want to write a file into document directory.
Hope this will help.
Following the Apple docs here I have been able to successfully load a GarageBand EXS sampler instrument into AUSampler in my iOS app by recreating, for example the following path within my app directory:
/Sampler Files/Funk Horn Section/nameofaudio.aif
iOS looks for the audio file in the following directory:
file:///Library/Application%20Support/GarageBand/Instrument%20Library/Sampler/Sampler%20Files/Funk%20Horn%20Section/'
However this doesn't work when I create my own EXS file. How does it know to remove the first part of the filepath if GarageBand?? I've even tried creating my EXS instrument and even created in the same GarageBand directory but it makes no difference:
Failed to locate sample '001%20VirusTI%20-%20SeaThr%2314A1B3.aif -- file:///macSSD/Library/Application%20Support/GarageBand/Instrument%20Library/Sampler/Sampler%20Files/VirusTI%20-%20SeaThreeHS%20v2/'
I've also tried manually editing the file path in the exs file with a text editor but nothing works.
The EXS instrument plays fine in logic. But my app can't find it.
Any help greatly appreciated.
The key here is that your source sampler file has to reference samples that come from any of these 'trigger' directory structures to work properly:
"/Sounds/"
"/Sampler Files/"
"/Apple Loops/"
"/EXS Factory Samples/"
"/SoundFont Samples/"
Your sample has to exist in a directory path with one of those triggers in it, and then the path has to match the exact same in your bundle. iOS looks for one of those triggers, then deletes everything before that, and uses that as the new search path in the bundle to find your sample.
It is tricky, but it will work this way if you make sure everything is in order.
I fought with this because my samples were stored in places without any of those keywords, and so it would never find them.
I developed an Ipad app which download different kind of files, but after a week or some days the downloaded files are removed and the app that open the file can find it anymore.
Could anybody help me, Where should I save downloaded files in my app to avoid that the file came automatically deleted?. IOS usually remove downloaded files after certain time?.
I already read this apple documentation
I know that maybe is not something complicated but I can't figure out why the file is removed If anybody can help me I'll appreciate that.
Put data cache files in the /Library/Caches
directory. Examples of files you should put in this directory include
(but are not limited to) database cache files and downloadable
content, such as that used by magazine, newspaper, and map apps. Your
app should be able to gracefully handle situations where cached data
is deleted by the system to free up disk space.
Most probably you are using caches/temp directory which the system can clear contents of in case of low space. To avoid deletion use Documents Directory.
If you are already storing in documents directory, then the file can appear missing if you are storing its hardcoded path , which can change during app update. Try storing relative path and log the contents of your documents directory to see what files exist.
save the files in your local sqlite db, data core or if you can serialize them with the standard user defaults