You need an amplifier, specifically, an audio amplifier. You face two big challenges:
You are using an Arduino's "digital" output to generate your "audio"
You are using a dynamic speaker (voicecoil-style) element design
There are many ways to do this. If fact many textbooks have been written about audio amplification and amplifier design. I will give you one (of many possible) solutions to your problem and explain the theory of operation and design decision calculus.
The type of speaker element you are building is dynamic (meaning that it relies on electromagnetic, rather than electrostatic, forces to generate motion in the diaphragm). The effect it has on you here is that you need to generate a bipolar drive signal to maximize your audio output.
The fabric/paper design of your speaker does not provide a lot of restoring force so to make it vibrate optimally, you need to pull it towards your permanent magnet -- but then actively push it away (not just stop pulling it). To do that you will need to reverse the direction of the current flowing in the electromagnet (the coil attached to the textile diaphragm).
This poses a problem for the Arduino because, like most digital stuff, it runs from a unipolar power source -- it can only drive its digital pins "high" to the power rail, or "low" to the reference ("ground"). Current can only flow in one direction ("high" to "low", I'm simplifying the physics here, don't shoot).
Further, the Arduino's output pins cannot supply a lot of power and using them directly near their maximum SOR is a bad idea for long-term reliability, especially with a dynamic element that provides back-EMF (the speaker coil stores energy that it can return to the "output", temporarily making the output accept it back -- outputs, like bullies, don't like that).
To solve these problems, I recommend this:
This circuit is simplified to improve clarity. There are some build details and features omitted. At the request of the community, I'll elaborate:
The schematic I first proposed contained two BJT's without biasing and positioning. It was intended to illustrate the push-pull nature of the class C implementation required by your scenario. However, it could not (and was not intended to) be built exactly as drawn. It turned out not to be a good idea as it landed somewhere between a reference design and a block diagram without being clearly in either camp. This, obviously, led to confusion.
So the schematic has been updated to something that can be built as drawn. However, when choosing specific transistors, batteries, etc... the values of R1 and R2 may need to be adjusted. Want help, just ping me the parts you chose.
You should also take notice of the fact that this circuit is always driving the speaker element. If you stop the oscillation of your "audio" output, the speaker will be stuck extruded and drawing power. You could isolate the speaker element with a series capacitor or an explicit enable/disable function could be added to handle this case, but I won't bother unless it is specifically requested.
Given the wide range of approaches to this circuit, I chose to focus on the concepts rather than the specifics. If you just want a reference design you can build for fun, let me know and I'll provide it.
Use two batteries to create a bipolar power source. Now, from the speaker's perspective one battery produces a positive voltage and the other a negative one. Really it's all a matter of perspective (where you define "zero").
From the Arduino's vantage point V2 = 3V (let's say its a 3V battery); V1=V2; the top of V1 looks like 6V
From the speaker's vantage point the top of V1 looks like 3V; the top of V2 looks like 0V; the bottom of V2 looks like -3V
The rest of the circuitry between the speaker and the Arduino is a two-stage amplifier.
This amplifier is a common-source configuration (a class A amplifier if you must know ;-) ). It serves to amplify the voltage of the Arduino's output from it's unipolar-range to the bi-polar range of the speaker (the two batteries in series). If you want more detail just ask and I'll elaborate further.
This is a class C power amplifier that serves to amplify the current driving the speaker. Current is proportional to force. More current --> more force pulling on the diaphragm --> more acceleration of the diaphragm --> more air pressure generated --> "louder" sound.
A note about your "audio" signal
A digital output from the Arduino only has two states. Human audio is an analog phenomenon that has an infinite number of states. The signal you would naturally generate if you just toggle the output pin at your desired frequency is a square-wave that necessarily contains many additional frequencies (harmonics). This will result in your speaker sounding raspy (or sometimes described as "screechy"). If you want a more pleasant sound, you will need to implement class D modulation in your firmware.
A note about "shoot-through"
The square (two-state) drive of the Arduino in this application is significant. Many have correctly noted that a stacked driver configuration necessarily poses a risk that both devices could (will) turn on during the transition of the input signal. This is a well known behavior. Since the upper device connects to the high voltage in the system and the lower device connects to the low voltage in the system, if they are both on at the same time, the power supply may be shorted ("may" because "shorted", aside from absolute 0, has a relative meaning respecting the size and capabilities of the supply, circuit, and components).
However, the Arduino output transitions very quickly through the intermediate range between its two driving output levels. To better quantify the analysis, let's look at the edge:
Let's choose the NFET's to be Si4836Dy's and let's double those numbers to produce a theoretical worst-case PFET to go with it. This system could handle >22A from a >2.7V Arduino output (Arduino's are typically higher, so this is a nice worst-case). The larger current handling implies a large transistor, which will switch more slowly (which is worse for our predicament).
Absolute worst case for the transistors is 75nC of total gate charge, let's derate to 100nC. The total gate charge for the second stage is then 300nC (given our worst-case doubling for the PFET). Swinging the out of the second stage low is much slower than pulling it high, due to the lack of an active component (R2) in the high-side of the stage 1 amplifier.
Taking this case, tau = RQ/V, where R is R2; Q is 300nC, the total gate charge; and V is 5 (chosen to be even worse than before). Computing, tau = 25uS. Again, let's double it make the scenario even more unfavorable: 2tau = 50uS.
Let's say we are working with a 12V total (+/-6V). To make things bad, lets use a bunch of AA (EE91) in series. A good (bad) estimate of the ESR for this configuration is 20Ohms of internal resistance
Now we determine what (if any) shoot-through risk we face. Again, let's be ridiculously hard on ourselves. We'll assume a full-short (0 ohms) even though it isn't physically possible (the transitioning transistor channels have substantially more resistance than 0). That means that the batteries must absorb V^2/R Watts for 50uS -- or 360uJ on each cycle. Now let's pick a high frequency audio signal at 10kHz. That's 3.6J each second, but there are eight batteries --> 450mJ/battery each second.
A typical EE91 "AA" battery is designed to safely dissipate 5076J over an hour (the 1-C condition)... or 1.41 in a second. That equates to about a 3X safety margin after we took every opportunity to make the scenario unrealistically unfavorable.
For a hobbyist project, this approach proffers a number of advantages over other Class C schemes: It uses fewer components, produces strong bi-polar output, requires less tuning, is substantially more tolerant to component variation, and is simpler to build.
I know this is a dense topic and may be confusing at first encounter. If you still have questions, please follow-up and I'll try to elaborate.