Im trying to change the volume of sound bytes[] in C#. Im reading a sound file with FFMPEG and and wanna change the volume on the fly. I found some examples and but I didnt understand them.
public void SendAudio(string pathOrUrl)
{
cancelVid = false;
isPlaying = true;
mProcess = Process.Start(new ProcessStartInfo
{ // FFmpeg requireqs us to spawn a process and hook into its stdout, so we will create a Process
FileName = "ffmpeg",
Arguments = "-i " + (char)34 + pathOrUrl + (char)34 + // Here we provide a list of arguments to feed into FFmpeg. -i means the location of the file/URL it will read from
" -f s16le -ar 48000 -ac 2 pipe:1", // Next, we tell it to output 16-bit 48000Hz PCM, over 2 channels, to stdout.
UseShellExecute = false,
RedirectStandardOutput = true, // Capture the stdout of the process
Verb = "runas"
});
while (!isRunning(mProcess)) { Task.Delay(1000); }
int blockSize = 3840; // The size of bytes to read per frame; 1920 for mono
byte[] buffer = new byte[blockSize];
byte[] gainBuffer = new byte[blockSize];
int byteCount;
while (true && !cancelVid) // Loop forever, so data will always be read
{
byteCount = mProcess.StandardOutput.BaseStream // Access the underlying MemoryStream from the stdout of FFmpeg
.Read(buffer, 0, blockSize); // Read stdout into the buffer
if (byteCount == 0) // FFmpeg did not output anything
break; // Break out of the while(true) loop, since there was nothing to read.
if (cancelVid)
break;
disAudioClient.Send(buffer, 0, byteCount); // Send our data to Discord
}
disAudioClient.Wait(); // Wait for the Voice Client to finish sending data, as ffMPEG may have already finished buffering out a song, and it is unsafe to return now.
isPlaying = false;
Console.Clear();
Console.WriteLine("Done Playing!");
Your question not very well phrased. Imagine you were talking about an image and asked "how do I decrease the amount of Red in image bytes[]?". The answer would be that you have to decode byte[] into and RGB tuple of the appropriate bit depth, modify the R value and then convert back to a byte[]. Same thing here. You convert the byte[] into samples of the appropriate bit-depth, rescale, and then convert back to a byte[].
In your case there are 16 bits per sample so you need to join each pair of consecutive bytes into a short, scale it, and then split back apart.
Starting from where you read the byte[]:
for (int i = 0 ; i < blockSize/2 ; ++i)
{
// convert to 16-bit
short sample = (short)((buffer[i*2+1] << 8) | buffer[i*2])
// scale
const double gain = 0.5; // value between 0 and 1.0
sample = (short)(sample * gain + 0.5);
// back to byte[]
buffer[i*2+1] = (byte)(sample >> 8);
buffer[i*2] = (byte)(sample & 0xff);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.