-
Notifications
You must be signed in to change notification settings - Fork 554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question: does any of the samples show how to record to a file? #135
Comments
Oboe is focussed on audio I/O. It does not deal with synthesis or file I/O. But luckily there are lots of solutions for reading and writing sample files. libsndfile is very popular - https://github.com/erikd/libsndfile/ Or you could transfer the data to Java and use a Java solution. |
What if I want to save what the Oboe does to the audio, into an audio file? |
Also, I think what you've linked to is GNU, which is the problematic open sourced license ... :( |
If you can get the data into Java then you can use a modified version of this simple WaveFileWriter from JSyn. It is under Apache Open Source License. You could also convert that to C++. |
I wish I knew how to do it. Was a very long time since I programmed in C/C++. |
Oboe is a C++ API. Are you programming your audio engine in Java? If so then I recommend using the Android Java AudioTrack API. |
I want to record audio, hoping that I could find some APIs and capabilities and "hidden" features on C/C++ library that I can't with normal Java/Kotlin library. |
The C++ APIs have fewer features than the Java/Kotlin APIs. The C/C++ APIs are only for high performance and/or low latency. For audio recording, have you looked at MediaRecorder? https://developer.android.com/reference/android/media/MediaRecorder |
The closest sample we have is this codelab: https://codelabs.developers.google.com/codelabs/making-waves-2-sampler/index.html?index=..%2F..%2Findex#0 It's for the AAudio API but could easily be ported to Oboe. The only challenge would be to save the audio data which is stored in memory to a file. This can be done using the normal FILE operations in C++. More here: https://stackoverflow.com/questions/1992953/file-operations-in-android-ndk |
@philburk Yes, I have. I was just hoping I could find here some possible ways to overcome this: I've noticed the same apps that do overcome this issue - have JNI libraries. I was thinking that maybe using one here could help me figure out how to do it. But I also think that recording to a file is quite a basic need of any audio-related library. Even here, and even if the focus is on performance. |
I'll reopen this with a view to creating a sample which demonstrates how to use libsndfile or some other file I/O library to write to a file (maybe combined with FFmpeg). This wouldn't be included in the Oboe core library but we can show how to do this as it's a fairly common request. |
Isn't FFmpeg GNU or something? |
Also thank you for considering this. |
In the AAudio echo sample, there is an AudioEffect.cpp - process() method. This process() method reads from recording thread and sends it back to AAudio. Meanwhile the process() method is called by dataCallback(). So if one were to do file IO i.e. saving the recording to file, could it be done directly in process() - or is the suggested method to buffer it to some FIFO queue - and then use another thread to output that to file ? Because the documentation for dataCallBack() seems to suggest they don't want apps to be doing file IO there: https://developer.android.com/ndk/reference/group/audio.html#group___audio_1gad88ad53a723807879ba75d3b5e07c073
|
Yes, that's the correct approach. You shouldn't perform any blocking operations inside the callback as this could cause xruns (overruns or underruns). |
Thanks. |
Please do consider showing how to do it in the sample. |
@dturner Closed because it now has this sample? |
Apologies, I might have got a bit trigger happy on closing this. Will consider for future sample updates. |
Thank you |
@dturner @AndroidDeveloperLB |
@sheraz-nadeem Thanks. It has some issues (permissions request even after being granted and some random crash), but overall seems to work fine. |
@AndroidDeveloperLB Thanks for your feedback. I will definitely fix those issues and update the status here. Cheers |
I'm writing native code to capture audio from an external USB device and encode it via ffmpeg into an mp4 (m4a) container. I've seen the Wavemaker2 sample that uses AAudio to capture audio data and play it back. I'm sticking with Aaudio for the moment but will translate to Oboe once it's working (which I understand to be straightforward). Naively, I was going to use something like that sample to call ffmpeg's avcodec and avformat functions on each callback. However, I've just read about how these callbacks must not perform blocking operations. I've looked at @sheraz-nadeem's code but it assumes relatively brief total duration (10secs) so that everything can be stored and written to a file at the end. In my case, users might want to record for hours, so I will have to write concurrently. Has anyone done anything like that? |
That's true, but if you don't need a low latency stream then you can use non-blocking reads rather than a callback. If that's the case then I would start a new thread which periodically does the following:
You'll need to ensure your input buffer capacity is large enough to hold all recorded data between iterations otherwise you'll get overruns (because the buffer will be full). You can check the buffer capacity using If you do get overruns you'll need to have your own, larger, buffer which you write the recorded data into. You'll probably want some way of communicating between your read/encode thread and your UI thread (e.g. the duration of the recording thus far), in this case I'd use an |
@AndroidDeveloperLB Any reason for closing? I was going to keep this open as a feature request for future sample apps |
OK. Sorry |
I thought the sample was updated. |
Thanks. I'm looking for low latency wherever possible and so I've implemented a simple buffering policy whereby the callback is filling one buffer (a few seconds' worth) while another thread encodes the previous filled buffer using ffmpeg. Seems to be working although I wouldn't want to post code until I'm sure. |
I'm working on a similar feature. Any progress @Tim-Kindberg ? |
The solution I mentioned worked: a two-buffer solution where one buffer (sufficient for a second of audio) was being filled at low-latency while the other buffer was being encoded and stored (takes a few hundred milliseconds even on old phones). I swap the buffers when one gets filled. This is fine for recording but I recently had to adapt the implementation for live streaming, where I can't get away with that 1-second throughput latency. I've now found an open-source non-blocking circular buffer implementation which seems to work fine: https://moodycamel.com/blog/2013/a-fast-lock-free-queue-for-c++.htm I'm just glad I didn't have to debug any of it! |
@dturner My use case includes calculating frequency from the low latency callback while also recording audio to .m4a files. My application has been doing the frequency calculation for a while and to add the audio recording I have to build on the same AudioStream (exclusive stream so can't use MediaRecorder or AudioRecord in conjunction). I'm thinking to implement the double buffer to do the encoding on a separate thread as we should. I just saw your Medium post about ffmpeg. Would you suggest using ffmpeg to continuously encode short int audio data to an .m4a file? |
I cannot make this work... Reported issue sheraz-nadeem/oboe_recorder_sample#4 |
Yes, that seems like a reasonable solution, or you could use I'm going to close this issue now. With limited resources adding this to our code samples isn't a priority at the moment. Hopefully the guidance in this issue will help anyone interested. Feel free to ask further questions on here (or perhaps better, on StackOverflow with the [oboe] tag). |
Good decision to close this issue. I think oboe team had given more than enough guidance on this. I just wanted to mention that people can also look at OboeTester's RECORD AND PLAY. |
If so, to which file formats?
If not, can you please show how to do it?
It's just that I've tried them, and I don't think any of them do it.
The text was updated successfully, but these errors were encountered: