Can't create stream from multichannel M4A file - but Audacity can open it???

Started by trojannemo,

mhuellwegen

Quote from: trojannemo... these are not proper .m4a files but fragmented MP4 files ...
Okay, but In my case, stem files for djing, (also the purchased ones) and the generated mp4 files from various software tools are in most cases aac encoded, also the free ones from native instruments.

But the more interesting thought could be, that they are what you called "fragmented" - I have not yet had a deep look into the files but I guess that this is the method they are arranged (for backwards compatibility) so a normal stereo player can see and also can play these files as normal stereo files (the stereo master sum in chan 1/2) as well as other multi channel players have also access to the other stereo tracks for separate bass, drums, vox and instruments playback inside the mp4.

And this is the behavior i noticed by using bass.dll. Bass only offers me the first stereo master (for normal playback, no djing) while the other 8 channels are not accessable at the moment (like a normal mp4 player would do as well).

By using the free ffmpeg tool "ffprobe" you can inspect the mp4 files and will notice, that the data of the first stereo stream was marked as "default".

If you like you can contact me and i will also have a deeper look into your files?

I currently have a project where i like to output the channels 3-10 of an mp4 audio file on my 8 channel usb-c interface by using ASIO.


Regards,

Martin

mhuellwegen

This is what I can see if I check one of my files with the ffprobe tool:

Metadata

five stereo aac encoded streams 0:0[0x1] (default) ... 0:4[0x5]

one video track 0:5[0x0] used by still image 500x500 as cover of the track (attached pic)



[mov,mp4,m4a,3gp,3g2,mj2 @ 0000016dc0132600] stream 0, timescale not set
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'stem.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 1
    compatible_brands: isom
    creation_time   : 2015-12-22T20:39:28.000000Z
    title           : Trovinsky
    artist          : Native Instruments
    album           : Neon Drive
    genre           : Synthpop, Electro, 80s
    AUDIOTYPE       : STEM
    publisher       : Native Instruments
    LABEL           : Native Instruments
  Duration: 00:04:22.06, start: 0.000000, bitrate: 1249 kb/s
  Stream #0:0[0x1](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 259 kb/s (default)
    Metadata:
      creation_time   : 2030-04-15T12:10:58.000000Z
      vendor_id       :
  Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 247 kb/s
    Metadata:
      creation_time   : 2032-05-31T05:32:02.000000Z
      vendor_id       :
  Stream #0:2[0x3](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 238 kb/s
    Metadata:
      creation_time   : 2034-07-16T22:53:06.000000Z
      vendor_id       :
  Stream #0:3[0x4](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 245 kb/s
    Metadata:
      creation_time   : 1970-02-18T11:53:54.000000Z
      vendor_id       :
  Stream #0:4[0x5](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 247 kb/s
    Metadata:
      creation_time   : 1972-04-05T05:14:58.000000Z
      vendor_id       :
  Stream #0:5[0x0]: Video: mjpeg (Baseline), yuvj444p(pc, bt470bg/unknown/unknown), 500x500, 90k tbr, 90k tbn (attached pic)

mhuellwegen

STEM files are therefore very similar to "multilingual" mp4 video files.

Different languages (subs) in mono, stereo, ... 5.1 or even more channels as a group.
Each group of channels is then assigned to a specific language or in our case an instrument (guitar, vox, ...).

In the end an mp4 STEM file has one or multiple groups of e.g. 2 channel stereo tracks,
in our case 1 "default" + 4 "other" groups of 2 channel stereo streams = 10 separate channels.

Can that make sense?

Ian @ un4seen

Quote from: trojannemoI've been working with multitrack files since 2011. They've always been ogg files, which I can load and do a million things with thanks to Bass.dll, Bass.Net and the addons. The twist here is that these new files are .m4a in extension but are not recognized by Bass as AAC, MP4 or Opus files. Per Ian, and I have no reason not to trust him since he's the one that created Bass.dll, these are not proper .m4a files but fragmented MP4 files.

They are still valid MP4 files, but rather than having one big block of media data ("mdat"), they have multiple smaller blocks, ie. the data is fragmented. fMP4 is usually used for streaming and I think less well supported (eg. BASS_AAC doesn't support it), so it seemed a bit strange to see in a standalone file, but perhaps it is common for MP4 Opus? Or perhaps it's just due to the encoder settings that were used to create the files?

Are you creating the files yourself, and if so, do you really need them to be MP4 Opus instead of regular Ogg Opus? Ogg Opus can handle 10 channels, and will already work with BASSOPUS.

Quote from: mhuellwegenSTEM files are therefore very similar to "multilingual" mp4 video files.

Yes, your file has 5 stereo tracks rather than a single 10-channel track. BASS and BASS_AAC currently always play the first audio track in an MP4 file. It is technically possible to add the option of playing the other tracks with BASS_AAC, but I'll have to check about when using the various OS MP4/AAC decoders - it'd be best if any such option was universally available.

mhuellwegen

@Ian

btw, I send you the "10 mono channels" wav file as well (included in the zip folder)...

While

   BASS_ChannelGetInfo(hChannel, &info);

show me the right amount of channels ... 0x00a = 10 channels,

   BASS_ASIO_ChannelEnableBASS(FALSE, 0, hChannel, TRUE)

in my case fails.

   DWORD dwError = BASS_ASIO_ErrorGetCode();

returns 0x12. Can you tell me what the Error Code 0x12 means since not every error code
was handled by a #define BASS_ERROR_ ... in bass.h or bassasio.h

Any ideas about that? Is it possible that this error was caused in my case by the fact that my ASIO Device only has 8 Output channels?
And if so, is there a prefered way to map individual channels (in my case the channels 3-10 = 8 channels) to my 8 outputs of my ASIO device?


Regards,

Martin

PS: Is there a way to donate you for all your work on bass.dll?

trojannemo

Quote from: Ian @ un4seenAre you creating the files yourself, and if so, do you really need them to be MP4 Opus instead of regular Ogg Opus? Ogg Opus can handle 10 channels, and will already work with BASSOPUS.

These are files used in the video game Fortnite Festival. They are indeed streamed to the players but it is possible to download them in chunks and they create this output file when put together. I don't have a say in the format of the files, if I did I would have just chosen ogg which is my preferred format.

Ian @ un4seen

Quote from: mhuellwegenbtw, I send you the "10 mono channels" wav file as well (included in the zip folder)...

While

   BASS_ChannelGetInfo(hChannel, &info);

show me the right amount of channels ... 0x00a = 10 channels,

   BASS_ASIO_ChannelEnableBASS(FALSE, 0, hChannel, TRUE)

in my case fails.

   DWORD dwError = BASS_ASIO_ErrorGetCode();

returns 0x12. Can you tell me what the Error Code 0x12 means since not every error code
was handled by a #define BASS_ERROR_ ... in bass.h or bassasio.h

Any ideas about that? Is it possible that this error was caused in my case by the fact that my ASIO Device only has 8 Output channels?
And if so, is there a prefered way to map individual channels (in my case the channels 3-10 = 8 channels) to my 8 outputs of my ASIO device?

Error code 0x12 (18) is BASS_ERROR_NOCHAN, which means the device does not have enough channels to accommodate the BASS channel, ie. it doesn't have 10 channels in this case. You could use a mixer to get around that, ie. create an 8-channel mixer (with BASS_Mixer_StreamCreate) for BASS_ASIO_ChannelEnableBASS and plug the 10-channel file into that. You could also use matrix-mixing (BASS_MIXER_CHAN_MATRIX) if you would like the extra 2 channels to be heard on any of the other channels, or if you want to rearrange them in any other way.

Quote from: mhuellwegenPS: Is there a way to donate you for all your work on bass.dll?

There isn't a donate option, but thanks for the offer! If you insist, you could purchase a Shareware licence. Perhaps it'll even come in useful in future :)

mhuellwegen

Quote from: trojannemoThese are files used in the video game Fortnite Festival. They are indeed streamed to the players but it is possible to download them in chunks and they create this output file when put together. I don't have a say in the format of the files, if I did I would have just chosen ogg which is my preferred format.
@trojannemo:

Ahh, okay, now it makes sense to me as well that your audio is "opus" audio in "ogg" container since "opus" is ideal for real-time communication and streaming.

In my case internet live streaming is in fact NOT involved.

I have hundreds of ACC encoded MP4 files on a hard drive, all with a 2 channel stereo default mix and with optional 4 more separate subs as separate stereo channels of audio to play with (e.g. make the musik like an acapella version for some secons during playback, like it was done regular in a dj set for mixing).

mhuellwegen

Quote from: Ian @ un4seenError code 0x12 (18) is BASS_ERROR_NOCHAN, which means the device does not have enough channels to accommodate the BASS channel.
Okay, that's what I had already thought...

Ian, can you add "BASS_ERROR_NOCHAN" and perhaps other missing error codes to bass.h and bassasio.h as well, since it makes debugging much easier?

mhuellwegen

Okay, my fault:

#define BASS_ERROR_NOCHAN   18   // can't get a free channel

is already defined.

mhuellwegen

Quote from: Ian @ un4seenYou could use a mixer to get around that (10 channels but 8 outputs only), ie. create an 8-channel mixer (with BASS_Mixer_StreamCreate) for BASS_ASIO_ChannelEnableBASS and plug the 10-channel file into that.
You could also use matrix-mixing (BASS_MIXER_CHAN_MATRIX)...
@Ian Thanx, BASS_MIXER_CHAN_MATRIX now working well for me with a 10 channel WAV file mapped to 8 ASIO outputs.

So in my special case the last remaining problem is the "fragmented" MP4 file that BASS can load successfully but will only grab and play channel 1+2 => the 1st stereo goup marked as "default".

Does this mean that it is a "demux of mp4/ogg" and not a "decoding of aac/opus" problem?

Regards,
Martin

trojannemo

For my part i'm giving up on this. Bass isn't ready to do what I need it to do. If I have to do half the work with the cutting edge release of Bass and the other half with a third party library that I don't know how to use, I might as well use ffmpeg which I do know how to use and works lightning fast.

public static int ProcessFortniteFile(string file)
{
    var bin = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\";
    var ffmpeg = bin + "ffmpeg.exe";
    if (!File.Exists(ffmpeg))
    {
        Console.WriteLine("ffmpeg.exe is missing and is required ... process aborted");
        return 0;
    }
    var opus = bin + "temp.opus";     
    if (File.Exists(opus))
    {
        File.Delete(opus);
    }
    var arg = "-i \"" + file + "\" -codec copy \"" + opus + "\"";
    var app = new ProcessStartInfo
    {
        CreateNoWindow = true,
        RedirectStandardOutput = true,
        UseShellExecute = false,
        FileName = ffmpeg,
        Arguments = arg,
        WorkingDirectory = bin
    };
    var process = Process.Start(app);
    do
    {
        //
    } while (!process.HasExited);
    process.Dispose();
    if (!File.Exists(opus))
    {
        return 0;
    }           
    var stream = BassOpus.BASS_OPUS_StreamCreateFile(opus, 0L, File.ReadAllBytes(opus).Length, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
    File.Delete(opus);
    return stream;
}

This is the entire code and it integrates into my existing workflow perfectly.
I hope one day I can just narrow it down to one BASS_StreamCreateFile call but until then I'll rely on ffmpeg.

mhuellwegen

Quote from: trojannemopublic static int ProcessFortniteFile(string file)
@trojannemo
Can you and would you like to send me a fortnite file so i can have a look on it as well?

trojannemo

There's a link to a zip file with some of these fortnite files inside in reply #7 on this thread on the first page.

mhuellwegen

Quote from: trojannemoThere's a link to a zip file with some of these fortnite files inside in reply #7 on this thread on the first page.
Got the zip file, will look into the five m4a Files tomorrow.

trojannemo

Thanks.

If you can get it down to just Bass or Bass + integrated code where I manipulate the input data, that's worth it. If the only way to make it work is to integrate another program or library, it's probably not worth it for me unless it's a very lightweight dll and easy to integrate.

Ian @ un4seen

Quote from: mhuellwegenSo in my special case the last remaining problem is the "fragmented" MP4 file that BASS can load successfully but will only grab and play channel 1+2 => the 1st stereo goup marked as "default".

Does this mean that it is a "demux of mp4/ogg" and not a "decoding of aac/opus" problem?

Yes, your case is more of a demuxing issue, in that BASS (and BASS_AAC) currently always plays the first audio track in an MP4 file and not any other tracks that there may be. Your example file isn't actually an fMP4 (that was just trojannemo's files), but fMP4 is supported by Media Foundation, so the file would still be playable with BASS if it was fMP4.

The good news is that the various OS decoders (on Windows/macOS/iOS/Android) used by BASS for MP4/AAC support (without BASS_AAC) do appear to allow the track to be specified, at least in theory - I haven't confirmed it's working yet. It seems like your example MP4 file may have the same sound in all 5 tracks? If so, can you provide a file with different sound in each track? That'll be better for testing purposes.

Quote from: trojannemoFor my part i'm giving up on this. Bass isn't ready to do what I need it to do. If I have to do half the work with the cutting edge release of Bass and the other half with a third party library that I don't know how to use, I might as well use ffmpeg which I do know how to use and works lightning fast.
...
I hope one day I can just narrow it down to one BASS_StreamCreateFile call but until then I'll rely on ffmpeg.

To be honest, if you don't want to bother with MP4 parsing and you already have another working solution, then I think it would be best to stick with that for now. There will hopefully be a BASSMP4 add-on (for more flexible MP4 parsing/demuxing) at some point, but I can't say when that will be.

trojannemo

Quote from: Ian @ un4seenThere will hopefully be a BASSMP4 add-on (for more flexible MP4 parsing/demuxing) at some point, but I can't say when that will be.

I will wait patiently  ;D

trojannemo

I saw you issued the update for BASSOpus that supports raw opus. Still not an easy implementation with my fragmented files?

trojannemo

I've made a lot of progress on this. Got MP4/Opus parsing going on, my test file I have over 9,000 samples and I know the offset and size of each sample, plus I have its data. At first I wrote it all to file and it's almost 1:1 in file size with the original m4a file. I tried feeding the whole thing to the new bassopus with StreamCreate and no luck. I'm now trying to feed it sample by sample and I'm getting a memory violation exception at the BASS_OPUS_StreamCreate step. Any ideas what it could be?