Creating a Vi File to Read a .wav File

  • Download source - 162.9 KB

Introduction

One of my interests and hobbies is music.  This project is able to mix multiple WAV audio files into a single audio file, and so that the audio from each source WAV file volition be heard simultaneously.  This projection includes a C++ class that tin can be used to open up, read, and write WAV audio files.  It is derived from an AudioFile class, and the mixing part uses the AudioFile interface.  That style, other audio formats (such as FLAC and AIF) could be added in the futurity and the mixing function would still work.  For mixing audio files, the source sound files will demand to take the aforementioned sample rate and bit rate and same number of channels (mono or stereo).  No external libraries are required.

In addition to the WAVFile form and supporting code, I've included an application for mixing WAV audio files. The compiled awarding and the full source code are included in the link at the superlative of the article.

This project builds in Visual Studio 2022 (I used the free Community version).  Note that to build the projection, you will need to take the C++ toolset installed in Visual Studio, forth with MFC.  The code uses mod C++ features, such as std::thread, a lambda part, std::shared_ptr, and a modernistic way of iterating through a collection.

Years ago, I published a version of this in C#: https://www.codeproject.com/Articles/35725/C-WAV-file-class-sound-mixing-and-some-light-audio

Included Application

The source code includes a GUI awarding (written in MFC) for choosing and mixing WAV audio files.  The following is a screenshot of the application:

To add WAV files to the list, you can elevate & drop files onto the GUI, or for each line in the list, there volition be a "..." push button that lets you browse and choose a WAV file to add.

Groundwork

A WAV audio file consists of a header at the first of the file, which contains strings to place the file type ("RIFF" and "Wave"), as well as data about the audio contained in the file (number of channels, sample rate, number of bits per channel, size of the data, etc.). Following the header is all of the audio data. Digital audio data is numeric: each sample is an integer that represents the level of the audio signal at that point in time.

The general idea backside digital audio mixing is adequately simple: Until in that location are no more sound samples, the adjacent sound sample from each sound file is read, then they're added together and saved to the output file.  A bit more than needs to be done, though, to bargain with digital sound clipping.  Digital audio clipping is acquired by numeric range limitations of the values due to the sample size (i.e., 8 or 16 bits): When audio sample values are added together (or if the volume is increased), it's possible for the resulting values to get beyond the numeric range of the values. When that happens, the upshot is (oftentimes loud) pops and clicks in the audio, which is undesirable. So, in society to mix WAV files together, mixAudioFiles() (in AudioFileTools.h and .cpp) volition first analyze each sound file to make up one's mind the highest audio sample, and so reduce the book of all the samples while mixing them to avoid digital audio clipping.

Wikipedia has an article on audio clipping that describes information technology in more detail.

Using the code

The AudioFile class is a parent class for working with sound files, with some pure virtual methods to exist implemented in derived classes, such as the included WAVFile class.  The WAVFile grade can open, read, and write WAV audio.  Most of the class methods return an AudioFileResultType, which can be used as if it was a bool (in an 'if' statement, for instance), and if information technology's imitation, it contains error letters in the form of std::string.

The following are some of the more important methods in the WAVFile form:

  • WAVFile(const std::string& pFilename): Constructor that takes a filename
  • WAVFile(const std::cord& pFilename, const WAVFileInfo& pWAVFileInfo): Constructor that takes a filename and a WAVFileInfo objecct specifying the desired properties of the WAV file (sample rate, flake rate, number of channels, etc.)
  • WAVFile(const std::cord& pFilename, AudioFileModes pFileMode): Constructor that takes a filename and a file mode (read, write, read/write)
  • template <course SampleType> AudioFileResultType getNextSample(SampleType& pAudioSample): A templatized method that reads the next sample from the sound file (if it's open up in read or read/write mode).  For the template, the proper data blazon must be used (for case, for 16-fleck sound, you lot can apply uint16_t.
  • template <class SampleType> AudioFileResultType writeSample(SampleType pAudioSample): A templated method that writes an audio sample to the WAV file (if it's open in write or read/write way).  For the template, the proper data type must be used (for case, for xvi-bit audio, you tin can use uint16_t.

These are some important methods in the AudioFile course, which are pure virtual:

  • virtual AudioFileResultType getNextSample_int64(int64_t& pAudioSample): Reads the next audio sample from the sound file (if in read or read/write mode).  The audio sample is cast to an int64 so that it can be used in generic algorithms - Whether the audio information is 8-scrap, 16-bit, or another bitness, the audio sample is cast to 64-scrap.
  • virtual AudioFileResultType writeSample_int64(int64_t pAudioSample): Writes an audio sample to the audio file (if in write or read/write mode).  The sample parameter is an int64_t but will be cast down to the appropriate type when writing the sampel to the audio file.  This is to brand generic sound algorithms simpler - Whether the audio data is 8-chip, sixteen-flake, or another bitness, the audio sample is cast down to the appropriate type.

AudioFileTools.h and AudioFileTools.cpp defines the post-obit function (amongst others):

  • AudioFileResultType mixAudioFiles(const std::vector<std::string>& pFilenames, AudioFile& pOutFile): Mixes multiple sound files into a unmarried sound file.  The pFilenames parameter is a vector of strings containing the source filenames, and pOutFile is an AudioFile object representing the audio file where the mixed audio file will be saved.  pOutFile is an AudioFile so that the calling code can decide what format the mixed file should exist, and mixAudioFiles() volition be able to work with it.  Currently, merely WAV is implemented, just in the future, other audio file formats (such as FLAC, AIF, etc.) could be implemented.  Mixing sound files can accept some time (due to the file I/O), so if you're using this in a GUI awarding, information technology's recommended to do the mixing in a separate thread so that the GUI doesn't freeze.

The WAVFileInfo and AudioFileInfo classes incorporate information about the audio files, such as bitness, number of channels, sample rate, etc.

An instance of opening a WAV file and looping through to get each audio sample (assuming the sound file contains sixteen-bit audio):

WAVFile audioFile("          someAudioFile.wav"); AudioFileResultType upshot = audioFile.open(AUDIO_FILE_READ);          if          (result) {size_t          numSamples = audioFile.numSamples();for          (size_t          i =          0; (i          <          numSamples) && result; ++i)     {         int16_t audioSample =          0;         result = audioFile.getNextSample(audioSample);     } }          else          {     cerr          <          <          "          Error(s) getting audio samples:"          <          <          endl;     result.outputErrors(cerr); } audioFile.close();

Points of Interest

One interesting thing to note is that data in a WAV audio file is always fiddling-endian, per the specification. On big-endian systems, the byte order must exist reversed earlier manipulating the audio data, and the byte order for a sample must be reversed before saving it to a WAV file. My WAVFile course handles this automatically; for example, if the system is big-endian, then when retrieving audio samples from a WAV file or adding a xvi-fleck sample to a WAV file, the bye order will be automatically reversed so that the information is in the proper order.

In creating the WAVFile class, it was necessary to await up the WAV file format specification. I found many web pages describing the WAV file format. Each page has basically the same data, but with dissimilar notes. I found the post-obit four pages useful:

  • http://ccrma.stanford.edu/courses/422/projects/WaveFormat
  • http://www.sonicspot.com/guide/wavefiles.html
  • http://technology.niagarac.on.ca/courses/ctec1631/WavFileFormat.html
  • http://www.ringthis.com/dev/wave_format.htm

History

  • Dec 7, 2018: Submitted the first version of this commodity

Keep a running update of any changes or improvements yous've fabricated here.

gustafsonpereadesen.blogspot.com

Source: https://www.codeproject.com/Articles/1271123/Cplusplus-audio-mixing-and-WAV-file-AudioFile-clas

0 Response to "Creating a Vi File to Read a .wav File"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel