There are two parts to this:
One is the creation/derivation/storage of the digital representation of a sine wave. The other is the conversion of the digital representation of a sine wave to an analog voltage (if I understand what you want).
The easiest way to obtain the digital representation of a sine wave is a lookup table. Precompute the digital values, and store them in an array. Simple. It is up to you to decide how much resolution (both in vertical accuracy/number of bits and horizontal accuracy/number of samples) you require.
It is also possible to compute the values directly. There are a number of ways of doing this, but be aware that using floating point math on the Arduino is very slow and space-intensive. You may want to look at CORDIC for one possible solution to this.
Next is the conversion to analog. You are right, PWM is one way to do this, and one of the easiest as far as external components go: you only need an RC filter to smooth the PWM. However, PWM is limited in resolution, and performs poorly when your wave frequency becomes a significant fraction of your PWM frequency. Also, the Arduino doesn't run very fast, so your PWM frequency is limited.
Other DAC solutions (there are many many many, so I'm not going to go in depth on this):
R2R DAC: simple to construct, but requires precision resistors for decent resolution, limited in resolution, and requires many IO pins.
"proper" DAC: an I2C/SPI DAC can give you far better performance, but you will have to learn how to communicate with it. And it's going to be more expensive, and involve several components.
However, this route seems to me quite long, what other options do I have?
I'm not sure what you mean by "quite long", but this is pretty straightforward. For example, here's how I'd go about it:
- store a sine wave in a lookup table
- set up an interrupt to trigger at regular intervals
- in the interrupt, pull a value from the lookup table and write it to PWM
You can now vary the frequency of your sine wave by either adjusting your interrupt interval, or adjusting the increment of your LUT position. You can vary the amplitude by simply multiplying the LUT values by a variable.
This is quite straightforward.