I have the following method which basically converts an input audio file to a monophonic FLAC file.
Now I am getting Member has cyclomatic complexity of 21 (105%) message in Visual Studio, while I've taken care of improving it as in the beginning it was longer, now there's not much I can remove from it as it pretty much fulfills my needs.
Should I just ignore this warning ?
private static void Convert(string inputFile, string outputFile, IProgress<double> progress = null)
{
if (inputFile == null) throw new ArgumentNullException("inputFile");
if (outputFile == null) throw new ArgumentNullException("outputFile");
int stream = 0;
int mixer = 0;
try
{
stream = Bass.BASS_StreamCreateFile(inputFile, 0, 0,
BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN);
if (stream == 0) throw new BassException("Could not create stream");
var info = Bass.BASS_ChannelGetInfo(stream);
if (info == null) throw new BassException("Could not retrieve stream info");
var freq = info.freq;
mixer = BassMix.BASS_Mixer_StreamCreate(freq, 1,
BASSFlag.BASS_MIXER_END | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE);
if (mixer == 0) throw new BassException("Could not create mixer");
bool addChannel = BassMix.BASS_Mixer_StreamAddChannel(mixer, stream, BASSFlag.BASS_MIXER_NORAMPIN);
if (!addChannel) throw new BassException("Could not add stream to mixer");
long getLength = Bass.BASS_ChannelGetLength(stream);
if (getLength == -1) throw new BassException("Could not get channel length");
var encoder = new EncoderFLAC(mixer)
{
Force16Bit = true,
FLAC_Verify = true,
OutputFile = outputFile
};
if (!encoder.Start(null, IntPtr.Zero, false))
throw new InvalidOperationException("Could not start encoder");
const int samples = 65536;
const int bytes = (samples * sizeof(float)) | (int)BASSData.BASS_DATA_FLOAT;
var buffer = new float[samples];
long bytesRead = 0;
while (Bass.BASS_ChannelIsActive(mixer) == BASSActive.BASS_ACTIVE_PLAYING)
{
int getData = Bass.BASS_ChannelGetData(mixer, buffer, bytes);
bytesRead += getData;
if (progress != null) progress.Report(1.0d / getLength * bytesRead);
}
encoder.Stop();
if (getLength / sizeof(short) != bytesRead)
throw new InvalidOperationException("Output length not equal to input length");
}
catch (Exception ex)
{
throw new InvalidOperationException("Conversion failed", ex);
}
finally
{
if (stream != 0) Bass.BASS_StreamFree(stream);
if (mixer != 0) Bass.BASS_StreamFree(mixer);
}
}
1 Answer 1
I think your code would become much simpler and more readable if you encapsulated all the BASS-related functionality from into separate types.
Something like:
class Stream
{
private readonly int handle;
// add overload that supports setting offset and lenght, if you need that
public Stream(string inputFile, BASSFlag flags)
{
handle = BASS_StreamCreateFile(inputFile, 0, 0, flags);
if (handle == 0)
throw new BassException("Could not create stream");
}
public ChannelInfo GetInfo()
{
var result = Bass.BASS_ChannelGetInfo(stream);
if (result == null)
throw new BassException("Could not retrieve stream info");
return result;
}
// etc.
}
This would simplify the start of your code to just:
Stream stream = new Stream(inputFile,
BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN);
var info = stream.GetInfo();