public AudioMetadata ReadMetadata(Stream stream) { var mp4 = new Mp4Model(stream); if (mp4.DescendToAtom("moov", "udta", "meta", "ilst")) { return(new IlstAtomToMetadataAdapter(mp4, mp4.GetChildAtomInfo())); } throw new AudioUnsupportedException("No ilst atom found."); }
public AudioInfo ReadAudioInfo(Stream stream) { try { var mp4 = new Mp4Model(stream); mp4.DescendToAtom("moov", "trak", "mdia", "minf", "stbl", "stts"); var stts = new SttsAtom(mp4.ReadAtom(mp4.CurrentAtom)); var sampleCount = stts.PacketCount * stts.PacketSize; mp4.DescendToAtom("moov", "trak", "mdia", "minf", "stbl", "stsd", "mp4a", "esds"); var esds = new EsdsAtom(mp4.ReadAtom(mp4.CurrentAtom)); if (esds.IsAac) { mp4.Reset(); return(AudioInfo.CreateForLossy("AAC", esds.Channels, (int)esds.SampleRate, sampleCount, CalculateBitRate(mp4.GetChildAtomInfo().Single(atom => atom.FourCc.Equals("mdat", StringComparison.Ordinal)).Size, sampleCount, esds.SampleRate))); } // Apple Lossless files have their own atom for storing audio info if (!mp4.DescendToAtom("moov", "trak", "mdia", "minf", "stbl", "stsd", "alac")) { throw new AudioUnsupportedException("Only AAC and ALAC MP4 streams are supported."); } var alac = new AlacAtom(mp4.ReadAtom(mp4.CurrentAtom)); return(AudioInfo.CreateForLossless( "ALAC", alac.Channels, alac.BitsPerSample, (int)alac.SampleRate, sampleCount)); } catch (EndOfStreamException e) { throw new AudioInvalidException(e.Message); } }
internal IlstAtomToMetadataAdapter( [NotNull] Mp4Model mp4, [NotNull, ItemNotNull] IEnumerable <AtomInfo> atoms) { foreach (var atom in atoms) { var atomData = mp4.ReadAtom(atom); // ReSharper disable once SwitchStatementMissingSomeCases switch (atom.FourCc) { case "©nam": Title = new TextAtom(atomData).Value; break; case "©ART": Artist = new TextAtom(atomData).Value; break; case "©alb": Album = new TextAtom(atomData).Value; break; case "aART": AlbumArtist = new TextAtom(atomData).Value; break; case "©wrt": Composer = new TextAtom(atomData).Value; break; case "©gen": Genre = new TextAtom(atomData).Value; break; case "©cmt": Comment = new TextAtom(atomData).Value; break; case "©day": // The ©day atom may contain a full date, or only the year: var dayAtom = new TextAtom(atomData); if (DateTime.TryParse(dayAtom.Value, CultureInfo.CurrentCulture, DateTimeStyles.NoCurrentDateDefault, out var result)) { Day = result.Day.ToString(CultureInfo.InvariantCulture); Month = result.Month.ToString(CultureInfo.InvariantCulture); Year = result.Year.ToString(CultureInfo.InvariantCulture); } else { Year = dayAtom.Value; } break; case "trkn": var trackNumberAtom = new TrackNumberAtom(atomData); TrackNumber = trackNumberAtom.TrackNumber.ToString(CultureInfo.InvariantCulture); if (trackNumberAtom.TrackCount > 0) { TrackCount = trackNumberAtom.TrackCount.ToString(CultureInfo.InvariantCulture); } break; case "covr": CoverArt = new CoverAtom(atomData).Value; break; } } }