how to concatenate two wav audio files with 30 seconds of white sound using NAudio - audio

I need to concatenate two wav audio files with 30 seconds of whute sound between them.
I want to use the NAudio library - or with any other way that work.
How to do it ?
( the different from any other question is that i need not only to make one audio file from two different audio files .. i also need to add silent between them )

Assuming your WAV files have the same sample rate and channel count, you can concatenate using FollowedBy and use SignalGenerator combined with Take to get the white noise.
var f1 = new AudioFileReader("ex1.wav");
var f2 = new SignalGenerator(f1.WaveFormat.SampleRate, f1.WaveFormat.Channels) { Type = SignalGeneratorType.White, Gain = 0.2f }.Take(TimeSpan.FromSeconds(5));
var f3 = new AudioFileReader("ex3.wav");
using (var wo = new WaveOutEvent())
{
wo.Init(f1.FollowedBy(f2).FollowedBy(f3));
wo.Play();
while (wo.PlaybackState == PlaybackState.Playing) Thread.Sleep(500);
}

Related

Create valid h264 from partial stream of h264 video data and wrap as Mp4

Lets say that I am reading from data stream, and that stream is sending the content of an h264 video feed. Given I read from that stream and I have some amount of data consisting of an indeterminate number of frames (NAL?). Given that i know the framerate, and size of the originating video, how would I go about converting this snippet into a mp4 that i could view? The video does not contain audio.
I want to do this using nodejs? My attempts to do so have produced nothing resembling a valid h264 file to convert into mp4. My thoughts so far were to strip any data preceding the first found start code in the data and feed that into a file and use ffmpeg (currently just testing in the command line) to convert the file to mp4.
What's the correct way to go about doing this?
ie. something like this (it's in Typescript but same thing)
//We assume here that when this while loop exist at least one full frame of data will have been read and written to disk
let stream: WriteStream = fs.createWriteStream("./test.h264")
while(someDataStream.available()) { //just an example not real code
let data: Buffer = someDataStream.readSomeData() //just an example not a real method call
let file = null;
try {
file = fs.statSync("./test.h264");
} catch (error) {
console.error(error)
}
if(!stream.writable) {
console.error("stream not writable")
} else if(file == null || file.size <= 0) {
let index = data.indexOf(0x7C)
console.log("index: " + index)
if(index > 0) {
console.log("index2: " + data.slice(index).indexOf(0x7c))
stream.write(data.slice(index))
}
} else {
stream.write(data)
}
}
To handle a data stream, you'll need to emit fragmented MP4. Like all MP4, fMP4 streams begin with a preamble containing ftyp, moov, and styp boxes. Then each frame is encoded with a moof / mdat box pair.
In order to generate a useful preamble from your H.264 bitstream, you need to locate a SPS / PPS pair of NALUs in the H264 data, to set up the avc1 box within the moov box. Those two NALUs are often immediately followed by an I-frame (a key frame). The first frame in a stream must be an I-frame, and subsequent ones can be P- or B- frames. E
It's a fairly complex task involving lots of bit-banging and buffer-shuffling (those are technical terms ;-).
I've been working on a piece of js code to extract H.264 from webm and put it into fmp4. It's not yet complete. It's backed up by another piece of code to decode the parts of the H264 stream that are needed to pack it properly into fMP4.
I wish I could write, "here are the ten lines of code you need" but those formats (fMP4 and H264) aren't simple enough to make that possible.
Idk why none of those questions doesn't actually have an easy answer. Here you go, Node.js solution, i argument just in case you need to offset the search
const soi = Buffer.from([0x00, 0x00, 0x00, 0x01]);
function findStartFrame(buffer, i = -1) {
while ((i = buffer.indexOf(soi, i + 1)) !== -1) {
if ((buffer[i + 4] & 0x1F) === 7) return i
}
return -1
}

nodejs FFMPEG add multiple inputs not working

var ffmpeg = require('fluent-ffmpeg');
var proc =
ffmpeg()
.input('./_animation/overlay1_%04d.png')
.inputFPS(20)
.input('./_animation/overlay2_%04d.png')
.inputFPS(20)
.input('./_animation/static1.png').inputFPS(1)
.input('./_animation/static2.png').inputFPS(1)
.outputFPS(20)
.save('./public/_ugc/' + new Date() + '.mp4');
I would like to create a video which combining from 4 sources, i.e. overlay1 sequences, overlay2 sequences and two static images. However, it is now always shows only one of the sources only. How to combine them in each of the frame?
And since the sources are not in the same dimension, is it possible to set the x,y coordinate for the sources?
ffmpeg()
.input('./_animation/static1.png')
.input('./_animation/overlay1_%04d.png')
.inputFPS(20)
.input('./_animation/overlay2_%04d.png')
.inputFPS(20)
.input('./_animation/static2.png')
.complexFilter([
"[0]overlay=66:155[output0]",
"[output0][1]overlay=66:155[output1]",
"[output1][2]overlay=66:155[output2]",
"[output2][0]overlay=0:0[output3]",
"[output3][0]overlay=0:0[output4]"
], 'output4')
.outputFPS(20)
Lastly it works with the above code

Raw audio playback in Allegro 5

I'm writing a MOD player, trying to playback a sample using Allegro5 raw stream capabilities, I can't figure out the exact init parameters for the stream to play the loaded sample data from the mod file.
This is what I have:
xf::ModLoader ml;
ml.loadFromFile("C:\\Users\\bubu\\Downloads\\agress.mod");
// getSampleLength() returns # of data words
int sample_length = ml.getSampleLength(1) * 2;
const int8_t* sample_data = ml.getSampleData(1);
ALLEGRO_MIXER* mixer = al_get_default_mixer();
ALLEGRO_AUDIO_STREAM* stream = al_create_audio_stream(1, sample_length, 8363, ALLEGRO_AUDIO_DEPTH_INT8, ALLEGRO_CHANNEL_CONF_1);
al_attach_audio_stream_to_mixer(stream, mixer);
al_set_audio_stream_gain(stream, 0.7f);
al_set_audio_stream_playmode(stream, ALLEGRO_PLAYMODE_ONCE);
al_set_audio_stream_playing(stream, true);
al_set_audio_stream_fragment(stream, (void*)sample_data);
al_drain_audio_stream(stream);
First of all, freq param is hardcoded for the test (8363Hz), but, playing back at the specified frequency I don't get what I expect, and al_drain_audio_stream() gets stuck forever playing garbage in a loop...
Any help would be appreciated.
At the very least, you need to be calling al_get_audio_stream_fragment before you call al_set_audio_stream_fragment. Typically you'd feed these streams in a while loop, while responding to the ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT event. See the ex_saw example in the Allegro's source for some sample code: https://github.com/liballeg/allegro5/blob/master/examples/ex_saw.c

JAudioTagger Deleting First Few Seconds of Track

I've written a simple Groovy script (below) to set the values of four of the ID3v1 and ID3v2 tag fields in mp3 files using the JAudioTagger library. The script successfully makes the changes but it also deletes the first 5 to 10 seconds of some of the files, other files are unaffected. It's not a big problem, but if anyone knows a simple fix, I would be grateful. All the files are from the same source, all have v1 and v2 tags, I can find no obvious difference in the source files to explain it.
import org.jaudiotagger.*
java.util.logging.Logger.getLogger("org.jaudiotagger").setLevel(java.util.logging.Level.OFF)
Integer trackNum = 0
Integer totalFiles = 0
Integer invalidFiles = 0
validMP3File = true
def dir = new File(/D:\Users\Jeremy\Music\Speech Radio\Unlistened\Z Temp Files to MP3 Tagged/)
dir.eachFile({curFile ->
totalFiles ++
try {
mp3File = org.jaudiotagger.audio.AudioFileIO.read(curFile)
} catch (org.jaudiotagger.audio.exceptions.CannotReadException e) {
validMP3File = false
invalidFiles ++
}
// Get the file name excluding the extension
baseFilename = org.jaudiotagger.audio.AudioFile.getBaseFilename(curFile)
// Check that it is an MP3 file
if (validMP3File) {
if (mp3File.getAudioHeader().getEncodingType() != 'mp3') {
validMP3File = false
invalidFiles ++
}
}
if (validMP3File) {
trackNum ++
if (mp3File.hasID3v1Tag()) {
curTagv1 = mp3File.getID3v1Tag()
} else {
curTagv1 = new org.jaudiotagger.tag.id3.ID3v1Tag()
}
if (mp3File.hasID3v2Tag()) {
curTagv2 = mp3File.getID3v2TagAsv24()
} else {
curTagv2 = new org.jaudiotagger.tag.id3.ID3v23Tag()
}
curTagv1.setField(org.jaudiotagger.tag.FieldKey.TITLE, baseFilename)
curTagv2.setField(org.jaudiotagger.tag.FieldKey.TITLE, baseFilename)
curTagv1.setField(org.jaudiotagger.tag.FieldKey.ARTIST, "BBC Radio")
curTagv2.setField(org.jaudiotagger.tag.FieldKey.ARTIST, "BBC Radio")
curTagv1.setField(org.jaudiotagger.tag.FieldKey.ALBUM, "BBC Radio - 20130205")
curTagv2.setField(org.jaudiotagger.tag.FieldKey.ALBUM, "BBC Radio - 20130205")
curTagv1.setField(org.jaudiotagger.tag.FieldKey.TRACK, trackNum.toString())
curTagv2.setField(org.jaudiotagger.tag.FieldKey.TRACK, trackNum.toString())
mp3File.setID3v1Tag(curTagv1)
mp3File.setID3v2Tag(curTagv2)
mp3File.save()
}
})
println """$trackNum tracks created from $totalFiles files with $invalidFiles invalid files"""
I'm still investigating and it appears that there is no problem with JAudioTagger. Before setting the tags, I use Total Recorder to reduce the quality of the download from 128kbps, 44,100Hz to 56kbps, 22,050Hz. This reduces the file size to less than half and the quality is fine for speech radio.
If I run my script on the original files, none of the audio track is deleted. The deletion of the first part of the audio track only occurs with the files that have been processed by Total Recorder.
Looking at the JAudioTagger logging for these files, there does appear to be a problem with the header:
Checking further because the ID3 Tag ends at 0x23f9 but the mp3 audio doesnt start until 0x7a77
Confirmed audio starts at 0x7a77 whether searching from start or from end of ID3 tag
This check is not performed for files that have not been processed by Total Recorder.
The log of the header read operation also shows (for a 27 minute track):
trackLength:06:52
It looks as though I shall have to find a new MP3 file editor!
Instead of
mp3File.save()
could you try:
mp3File.commit()
No idea if it will help, but that seems to be the documented method?

How to play a spotify music stream

First of all, i am new to audio-programming, so bear with me.
I am trying to play spotify music with NAudio or BASS.Net or any other .net audio-library.
As far as i known, libspotify delivers music as raw PCM data. what is the sample rate of spotify stream (libspotify)?
From the spotify docs:
Samples are delivered as integers, see sp_audioformat. One frame consists of the same number of samples as there are channels. I.e. interleaving is on the sample level.
When i try to play a song, spotify makes a callback with a 8192 byte buffer
channels = 2
sample_rate = 44100
num_frames = 2048
I need a little help translating this information to NAudio terms.
I have also tried with a spotify to Bass.Net sample (BASSPlayer.cs). But i haven't heard a single note from my speakers yet.
I have tried to play an mp3-song with NAudio and Bass.NET and this works fine, so the speaker volume is ok.
https://github.com/Alxandr/SpotiFire/blob/master/SpotiFire.Server/BASSPlayer.cs
There is breakthrough with NAudio. This is what i came up with, by using the trial and error method. I'm not sure if this is the right way to calculate the parameters from sampleRate/channels...
But the song is playing :-)
IWavePlayer waveOutDevice = new WaveOut();
using (var pcmStream = new FileStream(PcmFile, FileMode.Open))
{
const int songDuration = 264000;
const int sampleRate = 44100;
const int channels = 2;
var waveFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, sampleRate * channels, 1, sampleRate * 2 * channels, channels, 16);
var waveStream = new RawSourceWaveStream(pcmStream, waveFormat);
waveOutDevice.Init(waveStream);
waveOutDevice.Play();
Thread.Sleep(songDuration);
waveOutDevice.Stop();
waveStream.Close();
waveOutDevice.Dispose();
}

Resources