Correction of a signal through a transmitter
For the sake of not putting more stuff in the comments, I'll try describe how I would approach the problem, although I confess that I've never actually done this myself.

You mentioned yourself, that for the sake of simplicity, we can assume for now that the system is linear, so that all frequencies are distorted in a consistent way. Perhaps it's non-linear as a function of distance between transmitter and receiver, but let's assume for now that this distance is fixed. I also assume that time-invariance property holds.

Linear time-invariant (LTI) systems are nice in many ways, one of which is that they commute (note that this is generally not true for time-varying systems). In other words, if $L_1$ and $L_2$ are LTI, then $L_1(L_2(x[n])) = L_2(L_1(x[n]))$ This means that if you can work out how to correct the received signal for distortions caused by your channel after you've received the signal, the same correction can be applied as pre-distortion before you send it out. Note all the assumptions we made, so if these definitely do not hold, perhaps you should clarify and we can start relaxing them.

Now to the topic of how in the world do you compute the correction filter. There are two equally straightforward ways, depending on whether you need it to be and FIR filter or if you can allow it to be IIR.

The first thing you do is measure the impulse response of the system. This can be done in many ways. For seismic systems I've heard people use chirp deconvolutions and wavelet based methods (I don't know much about exact ones). I would start off by sending a chirp through your channel, recording it on the other end, taking FFT's of original and received signals, dividing recorded by original and taking the IFFT. I know I will probably get lynched for suggesting this, but this is a first step. This may actually work okay, so try it. You can then start experimenting with more sophisticated ways of obtaining the impulse response.

Once we've obtained this impulse response, call it $h[n]$, we need to invert it. From basic LTI system theory, we know that inverting $H(z)$ is done simply with $H^{-1}(z)=\dfrac{1}{H(z)}$. However, there's a catch. $H^{-1}(z)$ may not be stable if $H(z)$, which is a polynomial, has complex roots outside the unit circle on the complex plane. This can be remedied by converting $H(z)$ to a minimum-phase system. This can be done using real cepstrum, and if you have MATLAB with the signal processing toolbox, the rceps command will do that for you without any additional code (look up the documentation). Now we have an IIR all-pole filter that solves the problem.

If IIR is not a good option and you need an FIR filter, Linear Predictive Coding (LPC) can be used to approximate this filter with an FIR filter. Describing it is beyond what I'm going to describe here, but you're welcome to post more questions on these topics if you like. This is more of a system overview rather than the full solution, but working out the entire thing without knowing constraints and requirements of your project is impossible.