I need to write a software in JAVA which allows me to simulate the transfer of some images over a noisy channel while adding redundancy with a repetition code.Before going into code details and issues, here are some requirements:read files from a directory containing imagesfor each file, apply a repetition code (with n repetitions, user input)for each file, send the result of the repetition code on a simulated channel with a given error probability. This means reading each bit and flipping it if we have an errorfor each file, decode the file received from the channel and save it back as imageThe parameters for the simulation are:Files' folderNumber of repetitionsError probability (as coefficient^exponent)Output folderI ended up organizing the project with these classes:NoisyChannel - simulates the channel by reading a String of bits and applying the error based on some error modelSingleError - implements the single error model, meaning that we have a bit error if exponent times we generate a random number which is <=0.1RepetitionCoder - applies the repetition code by taking the bit String, generating a char[stringLength*repetitions] array and filling it with the generated repetitions (010 with 3 repetitions will turn to 000111000)RepetitionDecoder - decodes the bit String by splitting it every repetitions characters and applying a majority vote to each substring. The majority vote returns the most frequent character from the substring (001 will have 0 as result of the mjority vote)Converter - utility class that contains methods to convert a byte[] to a bit String and the other way aroundNow that you have a little bit of background, here's my problem: the simulation is really slow!I've tried with 15 images with a size of 2.2MB each (so roughly 30MB of data) and 5 repetitions and it took around 8 minute to complete, which is way too high for me (running on an i5-4670 3.4GHz, 16GB 1333MHz dual-channel RAM, files stored on an USB3.0 external drive because I don't want to mess with my SSD)This is why I need your help to try to speed things up.TestLoopfor (int i = 0; i < 15; i++) {    byte[] input = Files.readAllBytes(new File(D:\\testFrame.jpg).toPath());    String inputString = Converter.byteArrayToBitString(input);    int repetitions = 5, coefficient = 10, exponent = -3;    // Repetitions (encoding)    RepetitionCoder coder = RepetitionFactory.createRepetitionCoder(repetitions);    String repCoderOutput = coder.encode(inputString);    // Noisy channel    BaseError error = ErrorFactory.createError(coefficient, exponent);    NoisyChannel channel = new NoisyChannel(error);    String channelOutput = channel.transfer(repCoderOutput);    // Repetitions (decoding)    RepetitionDecoder decoder = RepetitionFactory.createRepetitionDecoder(repetitions);    String repDecoderOutput = decoder.decode(channelOutput);    byte[] output = Converter.bitStringToByteArray(repDecoderOutput);    Files.write(new File(D:\\testFrame_2.jpg).toPath(), output);}Converter.byteArrayToBitStringpublic static String byteArrayToBitString(byte[] source) {    StringBuilder sb = new StringBuilder(8 * source.length);    for (byte b : source) {        sb.append(byteToBitString(b));    }    return sb.toString();}RepetitionCoder.encodepublic String encode(String bitString){    return repeat(bitString);}private String repeat(String bitString) {    StringBuilder sb = new StringBuilder(bitString.length() * repetitions);    for (char c : bitString.toCharArray()) {        char[] chars = new char[repetitions];        Arrays.fill(chars, c);        sb.append(chars);    }    return sb.toString();}NoisyChannel.transferpublic String transfer(String input) {    char[] bits = input.toCharArray();    for (int i = 0; i < bits.length; i++) {        bits[i] = errorModel.addError(bits[i]);    }    return new String(bits);}SingleError.addErrorprotected char addError(char source) {    return (isError()) ? flipBit(source) : source;}protected boolean isError() {    for (int i = 0; i < Math.abs(exponent); i++) {        if (Math.random() >= 0.1) {            return false;        }    }    return !(coefficient > 0 && Math.random() >= coefficient / 10);}protected char flipBit(char bit) {    return (bit == '0') ? (char) 49 : (char) 48;}RepetitionDecoder.decodepublic String decode(String bitString) {    String[] repetitionsString = splitStringEvery(bitString, repetitions);    StringBuilder sb = new StringBuilder(repetitionsString.length);    for (String rep : repetitionsString) {        sb.append(majorityVote(rep));    }    return sb.toString();}private String[] splitStringEvery(String s, int interval) {    int arrayLength = (int) Math.ceil(((s.length() / (double) interval)));    String[] result = new String[arrayLength];    int j = 0;    int lastIndex = result.length - 1;    for (int i = 0; i < lastIndex; i++) {        result[i] = s.substring(j, j + interval);        j += interval;    }    result[lastIndex] = s.substring(j);    return result;}private char majorityVote(String buffer) {    int zeroes = (int) buffer.chars().filter(b -> b == 48).count();    return (zeroes > repetitions / 2) ? '0' : '1';}Converter.bitStringToByteArraypublic static byte[] bitStringToByteArray(String string) {    byte[] result = new byte[string.length() / 8];    for (int i = 0; i < string.length(); i += 8) {        String subString = string.substring(i, i + 8);        result[i / 8] = bitStringToByte(subString);    }    return result;}Any idea on how to speed things up while keeping a good readability? Considered that I need to work with 500+ images, wasting 8 minutes every 15 images leads to huge times.EDIT:Created the follow-up question as suggested.
Simulating image transfer over noisy channel with a repetition code
java;performance;strings;file system